我想用Mock测试一个void方法。
public class ConsoleTargetBuilder : ITargetBuilder
{
private const string CONSOLE_WITH_STACK_TRACE = "consoleWithStackTrace";
private const string CONSOLE_WITHOUT_STACK_TRACE = "consoleWithoutStackTrace";
private LoggerModel _loggerModel;
private LoggingConfiguration _nLogLoggingConfiguration;
public ConsoleTargetBuilder(LoggerModel loggerModel, LoggingConfiguration nLogLoggingConfiguration)
{
_loggerModel = loggerModel;
_nLogLoggingConfiguration = nLogLoggingConfiguration;
}
public void AddNLogConfigurationTypeTagret()
{
var consoleTargetWithStackTrace = new ConsoleTarget();
consoleTargetWithStackTrace.Name = CONSOLE_WITH_STACK_TRACE;
consoleTargetWithStackTrace.Layout = _loggerModel.layout + "|${stacktrace}";
_nLogLoggingConfiguration.AddTarget(CONSOLE_WITH_STACK_TRACE, consoleTargetWithStackTrace);
var consoleTargetWithoutStackTrace = new ConsoleTarget();
consoleTargetWithoutStackTrace.Name = CONSOLE_WITHOUT_STACK_TRACE;
consoleTargetWithoutStackTrace.Layout = _loggerModel.layout;
_nLogLoggingConfiguration.AddTarget(CONSOLE_WITHOUT_STACK_TRACE, consoleTargetWithoutStackTrace);
}
问题是我不确定如何测试它。我有我的主要代码。
public class ConsoleTargetBuilderUnitTests
{
public static IEnumerable<object[]> ConsoleTargetBuilderTestData
{
get
{
return new[]
{
new object[]
{
new LoggerModel(),
new LoggingConfiguration(),
2
}
};
}
}
[Theory]
[MemberData("ConsoleTargetBuilderTestData")]
public void ConsoleTargetBuilder_Should_Add_A_Console_Target(LoggerModel loggerModel, LoggingConfiguration nLogLoggingConfiguration, int expectedConsoleTargetCount)
{
// ARRANGE
var targetBuilderMock = new Mock<ITargetBuilder>();
targetBuilderMock.Setup(x => x.AddNLogConfigurationTypeTagret()).Verifiable();
// ACT
var consoleTargetBuilder = new ConsoleTargetBuilder(loggerModel, nLogLoggingConfiguration);
// ASSERT
Assert.Equal(expectedConsoleTargetCount, nLogLoggingConfiguration.AllTargets.Count);
}
请引导我走向正确的方向。
答案 0 :(得分:3)
在我看来,你根本不需要模拟。您正在测试AddNLogConfigurationTypeTagret。不是构造函数。
[Theory]
[MemberData("ConsoleTargetBuilderTestData")]
public void ConsoleTargetBuilder_Should_Add_A_Console_Target(LoggerModel loggerModel, LoggingConfiguration nLogLoggingConfiguration, int expectedConsoleTargetCount)
{
// ARRANGE
var consoleTargetBuilder = new ConsoleTargetBuilder(loggerModel, nLogLoggingConfiguration);
// ACT
consoleTargetBuilder.AddNLogConfigurationTypeTagret();
// ASSERT
Assert.Equal(expectedConsoleTargetCount, nLogLoggingConfiguration.AllTargets.Count);
}
如果您不想自己调用AddNLogConfigurationTypeTagret,则应在构造函数中调用它。这会将测试更改为:
[Theory]
[MemberData("ConsoleTargetBuilderTestData")]
public void ConsoleTargetBuilder_Should_Add_A_Console_Target(LoggerModel loggerModel, LoggingConfiguration nLogLoggingConfiguration, int expectedConsoleTargetCount)
{
// ARRANGE
// ACT
var consoleTargetBuilder = new ConsoleTargetBuilder(loggerModel, nLogLoggingConfiguration);
// ASSERT
Assert.Equal(expectedConsoleTargetCount, nLogLoggingConfiguration.AllTargets.Count);
}
然后类构造函数应为:
public ConsoleTargetBuilder(LoggerModel loggerModel, LoggingConfiguration nLogLoggingConfiguration)
{
_loggerModel = loggerModel;
_nLogLoggingConfiguration = nLogLoggingConfiguration;
AddNLogConfigurationTypeTagret();
}
答案 1 :(得分:2)
请指导我正确的方向,我想要两件事。 A)调用该方法。 B)添加了两个目标。所以预期的数量是2。
A)如果您想验证方法AddNLogConfigurationTypeTagret
是否已被调用,那么您需要在调用此方法的代码上对其进行测试。例如。类似于ConsoleTargetBuilderClient
的类是使用ITargetBuilder
的类的假设示例(在您自己的代码中,您应该拥有类{{}使用{1}} 。
ConsoleTargetBuilder
然后,您可以进行测试,以验证方法public class ConsoleTargetBuilderClient
{
private ITargetBuilder _builder;
public ConsoleTargetBuilderClient(ITargetBuilder builder)
{
_builder = builder;
}
public void DoSomething()
{
_builder.AddNLogConfigurationTypeTagret();
}
}
是否调用方法DoSomething
。为此,您可以使用AddNLogConfigurationTypeTagret
的模拟,因为您测试与它的交互。测试可能如下所示:
ConsoleTargetBuilder
B)如果您想验证是否已添加目标,则需要测试代码本身(而不是模拟它)。测试可能如下所示:
public void DoSomething_WhenCalled_AddNLogConfigurationTypeTagretGetsCalled()
{
// Arrange
bool addNLogConfigurationTypeTagretWasCalled = false;
Mock<ITargetBuilder> targetBuilderMock = new Mock<ITargetBuilder>();
targetBuilderMock.Setup(b => b.AddNLogConfigurationTypeTagret())
.Callback(() => addNLogConfigurationTypeTagretWasCalled = true);
ConsoleTargetBuilderClient client = new ConsoleTargetBuilderClient(targetBuilderMock.Object);
// Act
client.DoSomething();
// Assert
Assert.IsTrue(addNLogConfigurationTypeTagretWasCalled);
}
注意:基于Google价值与基于状态的交互测试。
答案 2 :(得分:1)
一般来说,你不应该嘲笑你想要测试的类,你应该嘲笑它的依赖。当你开始嘲笑课程时,你试图测试的东西经常会缠绕在一起导致脆弱的测试,而且很难确定你是在测试你的代码,还是在模拟设置,或者两者兼而有之。 / p>
方法AddNLogConfigurationTypeTagret
是您正在测试的类的公共方法,因为@Philip已经说过,您应该只是从测试中调用它,或者应该从构造函数中调用它。如果您的目标是从构造函数中调用它,那么我建议它应该是一个私有方法,除非有理由从类外部调用它。
就测试void方法调用的效果而言,您对该方法引起的状态更改感兴趣。在这种情况下,_nLoggingConfiguration
是否有两个目标添加了正确的属性。您没有向我们展示nLoggingConfiguration.AllTargets
属性,但我会假设您在测试中使用了Count
属性,您只需检查其中的项目即可。列表以确认已将正确的名称和布局添加到正确的目标类型。
答案 3 :(得分:0)
// Assert
targetBuilderMock.Verify(x => x.AddNLogConfigurationTypeTagret(), Times.Once());