2.5.0.1442单元测试总线.在某些单元测试中返回null

本文关键字:单元测试 返回 null 总线 1442 | 更新日期: 2023-09-27 18:08:38

我在使用saga进行NServiceBus单元测试时遇到了奇怪的行为。

运行
  • NSB 2.5.0.1442(由于IMessage而卡在这里,并且它在多个服务中)
  • NServiceBus。测试
  • Resharper 8.2单元测试运行器
  • VS2013 update最新rtm版本/package/thingy

我的解决方案中有三个单元测试项目。它们中只有一个引用了NServiceBus。测试,因为它是唯一一个测试Saga的。

  1. 消息。测试
  2. 服务。测试(此引用NSB.Testing)
  3. ViewModelUpdater。测试

单独运行单元测试项目,一切正常。

同时运行这三个会在Service.Testing中引入一些测试失败。即使在调试模式下运行所有项目的单元测试也会产生同样的问题。

我已经回溯到这段代码的问题。此后,我添加了命令== null检查,以使单元测试顺利失败,而不是返回愚蠢的rhino。模拟故障。

var command = Bus.CreateInstance<IEmailMessage>(a =>
{
    a.ToAddress = toAddresses;
    a.FromAddress = _formServiceEmailAddress;
    a.Subject = emailSubject;
    a.Body = body.ToString();
    a.IsHtmlBody = true;
});
if (command == null)
{
    throw new Exception("Email Message Failed to Create");
}
Bus.Send(command);

我没有包含测试代码,因为我已经从单元测试中删除了我的. expectsend代码,并且这里仍然失败。

Bus.CreateInstance<IEmailMessage> is returning null.

Bus不为空,我选择所有单元测试项目并运行调试。

写这个问题的时候,我可能离解决这个问题越来越近了。以下代码来自调试

时的quickwatch Bus
((IBusProxyc9a2035def74446cb4f71fea5bf76c47)(Bus))
+       __interceptors  {Castle.Core.Interceptor.IInterceptor[1]}   Castle.Core.Interceptor.IInterceptor[]

是否有可能"创建实例"已被代理并且不再工作?我不坐公共汽车。创建实例在我的传奇,但这个IEMailMessage是唯一的接口(它被我们所有的服务用来发送到一个标准的电子邮件发送者服务。

我刚刚重新设计了另一个消息,使用Bus.CreateInstance<>,但这次是在一个对象上,并得到了相同的问题。

我把同样的东西重做到Bus。发送后没有收到同样的问题。

我现在将我的原始代码更新为

Bus.Send<IEmailMessage>(a =>
{
    a.ToAddress = toAddresses;
    a.FromAddress = _formServiceEmailAddress;
    a.Subject = emailSubject;
    a.Body = body.ToString();
    a.IsHtmlBody = true;
});

运行单元测试,现在不会在该代码上抛出异常。

但是现在我的单元测试没有达到我的预期。

InitiatedTestSaga(command)
    .ExpectPublish<FinanceUserAccessFormSubmitted>(m => CompareSubmitted(m,command) )
    .ExpectPublish<AssignedToManager>(m =>
    {
        Console.WriteLine("AssignedToManager");
        return m.FormId == command.FormId;
    })
    .ExpectSend<CreateFormSummary>(m =>
    {
        Console.WriteLine("CreateFormSummary");
        return m.FormId == command.FormId;
    })
    .ExpectSend<CreateFormHistory>(m =>
    {
        Console.WriteLine("CreateFormHistory");
        return m.FormId == command.FormId;
    })
    .ExpectSend<UpdateFormSummary>(m =>
    {
        Console.WriteLine("UpdateFormSummary");
        return m.FormId == command.FormId;
    })
    .ExpectSend<IEmailMessage>(m =>
    {
        Console.WriteLine("IEmailMessage");
        return TestCommands.ExpectedReceipientIs(m, command.FormDetails.ManagerForApproval.EmailAddress);
    })      
    .ExpectReply<CompletionMessage>(m => m.ErrorCode == (int) ResponseCode.Success)
    .When(s => s.Handle(command));

输出

AssignedToManager
CreateFormSummary
CreateFormHistory
UpdateFormSummary
Rhino.Mocks.Exceptions.ExpectationViolationException : IBus.Send(callback method: <>c__DisplayClass2`1.<ExpectSend>b__1); Expected #1, Actual #0.

显示从未发送过IEmailMessage。

是否可能使用Bus. send<>与使用Bus. send<>不同?发送行为?是否可能现在发送的消息的顺序不同了?在saga代码中,iemailMessage是最后一条消息,因此应该是单元测试接收到的最后一条消息。

我们往回追溯一下。当我单独运行测试时会发生什么?下面是相同单元测试

的输出
AssignedToManager
CreateFormSummary
CreateFormHistory
UpdateFormSummary
IEmailMessage
ExpectedReceipientIs__["Manager@domain.com"]

所以当所有的测试项目都运行时,我们仍然有一个问题。我想,如果我改变期望的顺序,测试可能在运行所有期望时工作,但单独运行它将失败。

当改变IEmailMessage期望的顺序时,不管我把它放在哪里(甚至在发布期望之间),我得到这个错误消息

System.InvalidCastException : Unable to cast object of type 'CreateFormSummary' to type 'IEmailMessage'.

所以现在我的问题看起来不尊重它是一个接口。我将用具有相同属性的本地类替换IEmailMessage

创建这个

public class EmailMessage : IEmailMessage
{
    public string BCCAddress { get; set; }
    public string Body { get; set; }
    public string CCAddress { get; set; }
    public string FromAddress { get; set; }
    public bool IsHtmlBody { get; set; }
    public string Subject { get; set; }
    public string ToAddress { get; set; }
}
//replaced IEmailMessage with concrete
Bus.Send<EmailMessage>(a =>
{
    a.ToAddress = toAddresses;
    a.FromAddress = _formServiceEmailAddress;
    a.Subject = emailSubject;
    a.Body = body.ToString();
    a.IsHtmlBody = true;
}); 
//Run All Unit tests 
//output of this unit test
AssignedToManager
CreateFormSummary
CreateFormHistory
UpdateFormSummary
IEmailMessage
ExpectedReceipientIs__["Manager@domain.com"]

只是为了好玩,决定将我的代码还原回Bus。创建实例,看看是否仍然失败。

private void CreateAndSendEmail(string[] emailAddresses, string emailSubject, StringBuilder body)
{           
    string toAddresses = String.Join(",", emailAddresses);
    var msg = Bus.CreateInstance<IEmailMessage>(a=> 
    {
        a.ToAddress = toAddresses;
        a.FromAddress = _formServiceEmailAddress;
        a.Subject = emailSubject;
        a.Body = body.ToString();
        a.IsHtmlBody = true;
    })  ;
    if (msg == null)
    {
        throw new Exception("msg is null");
    }
    Bus.Send(msg);
}
//Run All Unit Tests
//output is this
AssignedToManager
CreateFormSummary
CreateFormHistory
UpdateFormSummary
IEmailMessage
ExpectedReceipientIs__
["Manager@wesleymission.org.au"]

加盖? !它是

我做了什么?我不确定。

我继续张贴这个问题,因为其他人可能会经历我所做的事情。此外,NSB/特定团队可能会感谢反馈。

我不会轻易放弃的

等一下,我不相信我做错了什么,让我再试着打破它。

  1. 关闭方案
  2. 删除所有Debug文件夹,
  3. 删除所有的obj文件夹。
  4. <
  5. 重建解决方案/gh>
  6. 关闭现有的测试会话
  7. 重新运行所有单元测试——通过
  8. 单独运行单元测试项目——pass

所以我的具体EmailMessages仍然存在,但我不再引用它了。所以我可以杀了它

  1. 删除具体的EmailMessages
  2. 重新运行所有单元测试——失败!
  3. 单独运行——pass

单元测试的输出

AssignedToManager
CreateFormSummary
CreateFormHistory
UpdateFormSummary
System.Exception : msg is null 

Saga正在调用两个实例bus。调用CreateInstance

解决方案

创建一个接口的实现,然后不使用它

2.5.0.1442单元测试总线.在某些单元测试中返回null

解决方案

创建一个接口的实现,然后不使用它