我有一个方法,它接受一个对象并将其保存到数据库中。但是,在我保存对象之前,我会执行以下操作...
if (IsAuthenticated)
{
foo.UserId = AuthenticatedUser.Id;
}
else
{
foo.AnonEmail = "Jon@World-Domination";
foo.AnonName = "Jon Skeet";
}
try
{
_fooService.Save(foo);
}
catch
{
// Some view, with error stuff now added to
return View(...); ViewData.ModelState.
}
// all good, redirect to the proper next view.
return RedirectToAction(...);
该代码工作正常,但我不确定如何编写两个单元测试以获得成功。 a)用户使用有效数据进行身份验证 b)用户未使用有效数据进行身份验证。
我不知道该怎么做的原因是两个场景都返回相同的RedirectToAction(..)视图对象。所以我可以成功测试..但它并没有告诉我保存的对象是否包含经过身份验证的用户ID或匿名信息。这就像我想要第一个单元测试说
想法?
常见的建议是我嘲笑fooService。我目前正在使用Dependency Injection和Moq,所以可以告诉我如何使用Moq?我不确定DI在这里是多么重要,不过???
答案 0 :(得分:3)
我会模拟_fooService
对象,并测试它作为测试的一部分收到的内容。这样,您的周围代码保持不变并且不受影响,并且通过检查_fooService
收到的内容,您可以断言行为是否符合预期。在这种情况下,返回对象不感兴趣。
你如何嘲笑你的_fooService
?您可以实现自己的“测试”版本(遵循与真实版本相同的界面),也可以使用模拟框架。无论您使用哪种方法,上面的代码都需要使用_fooService
的给定实现进行配置(通常在构建时 - 请参阅dependency injection以获取有关此方法的更多信息)
答案 1 :(得分:1)
您可以模拟_fooService.Save(foo)并检查提供的foo。
答案 2 :(得分:1)
也许您发现很难测试对象,因为您在一个方法中发生了多个活动。
这里的整体主题是控制器逻辑。
如果你提取另一个对象(IUserDecoratorService),那么你的代码就像
userService.UpdateUserInformation(foo);
try
{
_fooService.Save(foo);
}
catch
{
// Some view, with error stuff now added to
return View(...); ViewData.ModelState.
}
// all good, redirect to the proper next view.
return RedirectToAction(...);
这种方法很容易测试,因为它是2个简单的2个服务交互和你已经可以测试的路由决策。
现在您只需要为新服务编写测试:
[Test]
public void ShouldDecorateWithUserIdForAuthenticatedUser()
{
{setup authenticated user}
:
service.UpdateUserInformation(foo);
Assert.AreEqual(expectedId, foo.UserId);
Assert.IsNull(foo.AnonEmail);
Assert.IsNull(foo.AnonEName);
}
[Test]
public void ShouldSpoofTheAllKnowingSkeetIfAnonymousUser()
{
{setup anonymous user}
:
service.UpdateUserInformation(foo);
Assert.AreEqual(UnassignedId, foo.UserId);
Assert.AreEqual("Jon@World-Domination", foo.AnonEmail);
Assert.AreEqual("Jon Skeet", foo.AnonName);
}
答案 3 :(得分:0)
您仍然可以参考您的对象。在单元测试结束时,你不能只断言foo.AnonEmail或UserId的值是什么?
单元测试不应该触及外部源(这是一个集成测试),所以如果你走这条路,你应该模拟你的数据源,然后通过你的模拟测试。
答案 4 :(得分:0)
您是否可以在测试中访问foo?我假设它是班上的一个领域。是否有公共吸气剂?如果不是,你可能不得不使用Reflection(我假设在asp.net中可用,但我不太熟悉它)
答案 5 :(得分:0)
您希望使用DI将fooservice正确实现到您的对象中,因此在测试时您可以执行此操作;
(使用Moq)
[TestMethod]
public void Jon_Skeet_Is_Saved_If_User_Not_Authenticated()
{
bool jonWasSaved = false;
var mockFooService = new Mock<IFooService>();
mockFooService
.Expect(x => x.Save(It.Is<Foo>(foo => foo.AnonName == "Jon Skeet")))
.Callback(() => jonWasSaved = true;);
FooManager instance = new FooManager(mockFooService.Object);
Foo testFoo = new Foo();
testFoo.UserId = 1; // this is not the authenticated id
instance.baa(foo);
Assert.IsTrue(jonWasSaved);
}
您可能还想传递用于检查AuthetnicatedUser.Id的任何服务的模拟版本
HTH