C# 单元测试使用模拟的void方法?
我想用Mock测试void方法C# 单元测试使用模拟的void方法?,c#,unit-testing,moq,xunit,C#,Unit Testing,Moq,Xunit,我想用Mock测试void方法 public class ConsoleTargetBuilder : ITargetBuilder { private const string CONSOLE_WITH_STACK_TRACE = "consoleWithStackTrace"; private const string CONSOLE_WITHOUT_STACK_TRACE = "consoleWithoutStackTrace"; private LoggerMo
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);
}
公共类控制台GetBuilderUnitTests
{
公共静态IEnumerable控制台GetBuilderTestData
{
收到
{
返回新的[]
{
新对象[]
{
新的LoggerModel(),
新的LoggingConfiguration(),
2.
}
};
}
}
[理论]
[MemberData(“ConsoleTargetBuilderTestData”)]
public void ConsoleTargetBuilder_应该_添加_Console_目标(LoggerModel LoggerModel,LoggingConfiguration nLogLoggingConfiguration,int expectedConsoleTargetCount)
{
//安排
var targetBuilderMock=new Mock();
targetBuilderMock.Setup(x=>x.AddNLOGConfiguration类型Tagret()).Verifiable();
//表演
var consoleTargetBuilder=新的consoleTargetBuilder(loggerModel,nLogLoggingConfiguration);
//断言
相等(expectedConsoleTargetCount、nLogLoggingConfiguration.AllTargets.Count);
}
请引导我到正确的方向。在我看来,您根本不需要模拟。您正在测试AddNLogConfiguration TypeTagret,而不是构造函数
// Assert
targetBuilderMock.Verify(x => x.AddNLogConfigurationTypeTagret(), Times.Once());
[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);
}
如果您不想自己调用AddNLogConfiguration TypeTagret,则应在构造函数中调用它。这会将测试更改为:
[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();
}
在我看来,您根本不需要模拟。您正在测试AddNLogConfiguration TypeTagret,而不是构造函数
[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);
}
如果您不想自己调用AddNLogConfiguration TypeTagret,则应在构造函数中调用它。这会将测试更改为:
[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();
}
一般来说,你不应该模拟你想要测试的类,你应该模拟它的依赖关系。当你开始模拟这个类时,你试图测试的东西往往会交织在一起,导致脆弱的测试,很难确定你是在测试你的代码,还是在模拟设置,或者两者兼而有之
方法
addnlogConfiguration TypeTagret
是您正在测试的类上的一个公共方法,因此@Philip说过,您可能应该从测试中调用它,或者应该从构造函数中调用它。如果您的目标是从构造函数中调用它,那么我建议它可能应该是一个私有方法d,除非有理由从课堂外调用它
就测试void方法调用的效果而言,您感兴趣的是该方法引起的状态更改。在本例中,
\u nLoggingConfiguration
是否有两个添加了正确属性的目标。您不会向我们显示nLoggingConfiguration.AllTargets
属性,但我会从f假设您在测试中使用了Count
属性,您只需检查列表中的项目,确认已将正确的名称和布局添加到正确的目标类型。一般来说,您不应该模拟要测试的类,而应该模拟它的依赖项。当您启动mocki对您试图测试的类进行模拟通常会导致脆弱的测试,很难确定您是在测试代码,还是在模拟设置,或者两者兼而有之
方法
addnlogConfiguration TypeTagret
是您正在测试的类上的一个公共方法,因此@Philip说过,您可能应该从测试中调用它,或者应该从构造函数中调用它。如果您的目标是从构造函数中调用它,那么我建议它可能应该是一个私有方法d,除非有理由从课堂外调用它
就测试void方法调用的效果而言,您感兴趣的是该方法引起的状态更改。在本例中,\u nLoggingConfiguration
是否有两个添加了正确属性的目标。您不会向我们显示nLoggingConfiguration.AllTargets
属性,但我会从f假设您在测试中使用了Count
属性,您可以简单地检查列表中的项目,以确认已将正确的名称和布局添加到正确的目标类型中
请引导我到正确的方向,我想要两件事。A)调用了该方法。B)添加了两个目标。因此预期计数为2
A)如果要验证调用了方法
AddNLogConfigurationTypeTagret
,则需要在调用此方法的代码上对其进行测试。例如,类ConsoleTargetBuilderClient
是使用ITargetBuilder
的类的假设示例(在您自己的代码中,应该有使用类ConsoleTargetBuilder
的地方)
然后,您可以进行一个测试,验证名为方法
AddNLogConfiguration TypeTagret
的方法DoSomething
是否正确。为此,您可以使用ConsoleTargetBuilder
的模拟,因为您可以测试与该方法的交互。测试可能如下所示:
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);
}
public void AddNLogConfigurationTypeTagret_WhenCalled_ConsoleTargetsAdded()
{
// Arrange
const int expectedConsoleTargetCount = 2;
var loggerModel = new LoggerModel();
var nLogLoggingConfiguration = new LoggingConfiguration();
var consoleTargetBuilder = new ConsoleTargetBuilder(loggerModel, nLogLoggingConfiguration);
// Act
consoleTargetBuilder.AddNLogConfigurationTypeTagret();
// Assert
Assert.AreEqual<int>(expectedConsoleTargetCount, nLogLoggingConfiguration.AllTargets.Count);
}
public void DoSomething\u when-called\u addnlogconfigurationtypetagretgetscaled()
{
//安排
bool addNLogConfigurationTypeTagretWasCalled=false;
Mock targetBuilderMock=new Mock();
targetBuilderMock.Setup(b=>b.addnlogConfiguration类型tagret())
.Callback(()=>AddNLOGConfiguration类型TagretwasCalled=true);
ConsoleGetBuilderClient=新的ConsoleGetBuilderClient(targetBuilderMock.Object);
//表演
client.DoSomething();
//断言
IsTrue(AddNLogConfiguration类型TagretWasCalled);
}
B)如果您愿意