当有多个 return 的表达式时,如何对方法 return 进行单元测试?

When there are multiple expressions that return, how do you unit test where the method returned?

我想对我的方法进行单元测试,并确保方法 returns 当 condition1 = true:

public bool condition1{get;set;}
public bool condition2{get;set;}
public void Consume(IConsumeContext<mymessage> context)
{
    if (context.Message==null)
    {
        Logme("No message");
        return;
    }
    if (condition1)
    {
        Logme("condition1 is true");
        return;
    }
    if (condition2)
    {
        Logme("condition2 is true");
        return;
    }
    //do work
}

有没有办法知道方法 Consume 返回的确切位置?

当然。

单元测试是一种非常有针对性的测试,用于验证特定场景。在这种情况下,您的场景定义是,您想要验证当 Message 不为 null 且 Confition1 为真时,您的目标方法是由于 condition1 而不是由于 Message null 或 condition2 而返回的。

通过定义场景,我们已经为您的单元测试建立了先决条件。

IConsumeContext<mymessage> contextMock = new Mock<IConsumeContext<mymessage>>();
contextMock.Setup(c => c.Message).Returns("Not_A_Null_Value");

var obj = new UberConsumer();
obj.Condition1 = true;

// obj.Condition2 doesn't really matter.. so you could run a combination of the tests, 
// one for condition2 = true and another for false.

现在是最重要的部分。要验证您的目标代码是否因 Condition1 而返回,您还需要做一件事:

能够验证此调用确实是由目标代码发出的,并且是对 LogMe 的唯一调用。

 Logme("condition1 is true");

最好的方法是模拟这个方法,或者如果它不可模拟,将它抽象到一个接口中并模拟出来。如果它是一个简单的无害方法,它只是将字符串分配给一个变量,您可以断言该变量。让我们假设它是一个可模拟的方法。

所以你的测试看起来像这样..

// arrange
IConsumeContext<mymessage> contextMock = new Mock<IConsumeContext<mymessage>>();
contextMock.Setup(c => c.Message).Returns("Not_A_Null_Value");

var obj = new UberConsumer();
obj.Condition1 = true;

// obj.Condition2 doesn't really matter.. so you could run a combination of the tests, 
// one for condition2 = true and another for false.

// setup callback for the mockable LogMe method and capture the string parameter value
   // string capturedStringValue = null
   // mockLogMeObj.Setup(l => l.LogMe(It.IsAny<string>()).Callback(val => { capturedStringValue = val} );
   // you could also verify the call count

// act
uberConsume.Consume(contextMock.Object);

// assert

// assert that the captured parameter of Logme was "condition1 is true"
Assert.Equals("condition1 is true", capturedStringValue);

// assert that the LogMe was called only once.
//  mockLogMeObj.Setup(l => l.LogMe(It.IsAny<string>()).Verify(Times.Once());

这为您提供了对您想要验证的确切事物的最佳验证。

我假设 Moq 是这里的模拟框架,但它可以是您使用的任何东西。