我需要测试 Quartz Job。 Quarts 作业的作用是触发改变用户平衡的领域事件。手动它工作正常。
测试中的问题是Job根本不处理Outbox消息。 ProcessedOnUtc 保持为空。
测试:
[Fact]
public async Task Should_WinAuction_When_BuyoutPrice()
{
var user = User.Create(Guid.NewGuid(), "example", "[email protected]");
var userTwo = User.Create(Guid.NewGuid(), "example2", "[email protected]");
var oldBalance = user.Balance;
_userRepository.Add(user);
_userRepository.Add(userTwo);
await UnitOfWork.SaveChangesAsync();
var auction = Auction.Create(Guid.NewGuid(), "example", "description", 10m, 11m, DateTime.Now, user.Id);
_auctionRepository.Add(auction);
await UnitOfWork.SaveChangesAsync();
var command = new PlaceBidCommand(11m, userTwo.Id, auction.Id);
var result = await Sender.Send(command);
Assert.True(result.IsSuccess);
var bid = await _bidRepository.GetByIdAsync(result.Data.BidId);
Assert.NotNull(bid);
Assert.Equal(userTwo.Id, auction.WinnerId);
await Task.Delay(5000);
var updatedUser = DbContext.Users.FirstOrDefault(u => u.Id == userTwo.Id);
Assert.True(updatedUser.Balance != 10000);
}
石英注册:
Quartz:
services.AddQuartz(options =>
{
var jobKey = JobKey.Create(nameof(ProcessOutboxMessages));
options.SchedulerId = Guid.NewGuid().ToString();
options.SchedulerName = "OutboxMessages";
options.AddJob<ProcessOutboxMessages>(jobKey)
.AddTrigger(trigger => trigger.ForJob(jobKey).WithSimpleSchedule(schedule =>
{
schedule.WithIntervalInSeconds(1);
schedule.RepeatForever();
}));
});
services.AddQuartzHostedService(options =>
{
options.WaitForJobsToComplete = true;
});
工作
public async Task Execute(IJobExecutionContext context)
{
var messages = await _dbContext.OutboxMessages
.Where(x => x.ProcessedOnUtc == null)
.Take(20)
.ToListAsync();
foreach (var message in messages)
{
IDomainEvent? domainEvent = JsonConvert.DeserializeObject<IDomainEvent>(message.Content, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
if (domainEvent == null)
{
continue;
}
await _publisher.Publish(domainEvent);
message.ProcessedOnUtc = DateTime.UtcNow;
}
await _dbContext.SaveChangesAsync();
}
试试这个。
[Fact]
public async Task Should_WinAuction_When_BuyoutPrice()
{
// Arrange
var user = User.Create(Guid.NewGuid(), "example", "[email protected]");
var userTwo = User.Create(Guid.NewGuid(), "example2", "[email protected]");
_userRepository.Add(user);
_userRepository.Add(userTwo);
await UnitOfWork.SaveChangesAsync();
var auction = Auction.Create(Guid.NewGuid(), "example", "description", 10m, 11m, DateTime.Now, user.Id);
_auctionRepository.Add(auction);
await UnitOfWork.SaveChangesAsync();
var command = new PlaceBidCommand(11m, userTwo.Id, auction.Id);
var result = await Sender.Send(command);
Assert.True(result.IsSuccess);
var bid = await _bidRepository.GetByIdAsync(result.Data.BidId);
Assert.NotNull(bid);
Assert.Equal(userTwo.Id, auction.WinnerId);
// Act
await TriggerQuartzJobManually();
// Assert
var updatedUser = DbContext.Users.FirstOrDefault(u => u.Id == userTwo.Id);
Assert.True(updatedUser.Balance != 10000);
}
private async Task TriggerQuartzJobManually()
{
// Create and start scheduler manually
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
IScheduler scheduler = await schedulerFactory.GetScheduler();
await scheduler.Start();
// Define the job and trigger
var jobDetail = JobBuilder.Create<ProcessOutboxMessages>()
.WithIdentity("ProcessOutboxMessages")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("ProcessOutboxMessagesTrigger")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(1).RepeatForever())
.Build();
await scheduler.ScheduleJob(jobDetail, trigger);
// Wait enough time for the job to be triggered and processed
await Task.Delay(5000);
// Stop the scheduler
await scheduler.Shutdown();
}