(C#,Rhino Mocks,MbUnit)。
我有一个名为AccountManager的类,它有一个RegisterUser()方法。此方法返回void但会为任何错误抛出异常。 AccountManager调用IDataRepository调用其AddUser()方法来执行数据库插入。
我正在使用Rhino Mock模拟IDataRepository,并为模拟存储库中引发的异常的给定参数集抛出异常。
[Test]
public void RegisterKnownUser()
{
MockRepository mocks = new MockRepository();
IDataRepository dataRepository = mocks.StrictMock<IDataRepository>();
using (mocks.Record())
{
Expect.Call(() => dataRepository.AddUser("abc", "abc", "abc@abc.com", "a", "bc")).Throw(
new InvalidOperationException());
}
using (mocks.Playback())
{
AccountManager manager = new AccountManager(dataRepository);
Assert.Throws(typeof (InvalidOperationException), () => manager.RegisterUser("abc", "abc", "abc@abc.com", "a", "bc"));
}
}
此测试工作正常。
我的问题是如何处理提供给RegisterUser的args正确有效的情况。真正的IDataRepository不会返回任何内容,也不会抛出任何异常。所以简而言之,AccountManager的状态不会改变。这是否意味着我不需要测试AccountManager.RegisterUser,因为它会导致我无法在测试的类和方法中直接观察到任何内容。模拟中的状态测试对我来说有点味道。我想只要我单独测试IDataRepository.AddUser,那么我就不需要测试AccountManager.RegisterUser输入会导致类中没有任何可观察的输入。
提前致谢。
答案 0 :(得分:2)
如果AccountManager调用DataPrepository,那么您的测试用例仍会验证某些内容。此处的记录/回放验证是否进行了呼叫。如果未进行呼叫,则测试用例将失败。如果它是两次/错误的args,它将失败。
这可能是一个非常基本的测试用例,但它仍然很好,并且不要求你在mock对象中放置状态。
答案 1 :(得分:0)
您可能希望使用有效参数测试方法,以确保不会抛出任何异常。换句话说,您无法观察状态更改或使用返回值(因为它是无效的),但您可以观察到该方法无异常地运行。
顺便说一下,如果方法没有返回值也没有更改AccountManager
状态,它会改变其他方式(如果没有,那么你可能应该从代码中删除方法什么都没有)
例如,它可能会影响DataRepository
。或者在数据库中添加记录。在这种情况下,您至少可以测试数据是否已更改或是否已成功添加记录。或者它可能会记录一个事件,说明新用户已注册,因此您可以在测试中检查日志事件是否在此处。
我认为只要我单独测试IDataRepository.AddUser,那么我就不需要测试AccountManager.RegisterUser输入会导致类中没有任何可观察的输入
如果AccountManager.RegisterUser
除了参数执行之外没有向IDataRepository.AddUser
添加任何内容,那么,如果您已经测试IDataRepository.AddUser
,则不必测试它。如果它检查参数,调用AddUser
并执行其他操作,最好检查它的作用是否正确。
假设你有:
public void AddUser(string userName, string userMail, string passwordHash)
{
// [...] Add a user to the database.
}
public void RegisterUser(string userName, string userMail, string passwordHash)
{
if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(...);
if (string.IsNullOrEmpty(userMail)) throw new ArgumentNullException(...);
if (string.IsNullOrEmpty(passwordHash)) throw new ArgumentNullException(...);
if (!Checks.IsValidMail(userMail)) throw new ArgumentException(...);
this.AddUser(userName, userMail, passwordHash);
this.SaveToLog(LogEvent.UserRegistered, userName, this.IPAddress);
}
在RegisterUser
中,通过传递错误的参数并期待异常来测试前四行。不得测试第五行,因为您已经测试过AddUser
。最后,必须测试第六行以确保在使用有效参数调用RegisterUser
时,将创建日志条目。