【问题标题】:Difference in techniques for setting a stubbed method's return value with Rhino Mocks使用 Rhino Mocks 设置存根方法返回值的技术差异
【发布时间】:2011-02-24 02:01:30
【问题描述】:

下面这两种给方法一些虚假实现的主要区别是什么?

我在一个测试中使用第二种方式很好,但在另一个测试中,除非我使用第一种方式,否则无法实现行为。

所以(第一个),

using (test.Record()) //test is MockRepository instance
{
 service.GetUser("dummyName");
 LastCall.Return(new LoginUser());
}

vs(第二个)。

service.Stub(r => r.GetUser("dummyName")).Return(new LoginUser());

编辑

问题是第二种技术在测试中返回 null,而我希望它返回一个新的 LoginUser。第一种技术通过返回一个新的 LoginUser 来按预期运行。在这两种情况下使用的所有其他测试代码都是相同的。

[TestFixture]
public class AuthorizationTest
{
    private MockRepository test;
    private IMembershipService service;

    [SetUp]
    public void SetUp()
    {
        test = new MockRepository();
        service = test.Stub<IMembershipService>();

        using (test.Record())
        {
            service.GetUser("dummyName");
            LastCall.Return(new LoginUser());
        }

        //service.Stub(r => r.GetUser("dummyName")).Return(new LoginUser()); 
    }

    [Test]
    public void GetCurrentUser_UserIsAuthenticated_ReturnsCurrentUser()
    {
        var authStub = new AuthorizationStub_SetCurrentUserAuthenticated(service, true);

        LoginUser u = authStub.GetCurrentUser();
        Assert.That(u != null);
    }

    [TearDown]
    public void TearDown()
    {
        service = null;
        test = null;
    }
}

可能与界面中的重载有关吗?

public interface IMembershipService
{
    bool ChangePassword(string username, string oldPassword, string newPassword);
    LoginUser GetUser(string username);
    LoginUser GetUser(object providerUserKey);
    string ResetPassword(string username);
    bool ValidateUser(string username, string password);
}

在被测方法中导致问题的行是:

LoginUser currentUser = _repository.GetUser(identity.Name);

在调试模式下,identity.Name 永远不会为 null,并且始终是“dummyName”

【问题讨论】:

    标签: unit-testing rhino-mocks stubbing


    【解决方案1】:

    第二种方法是新的AAA syntax,是首选方法。也许您可以扩展使用 AAA 语法时遇到的问题,并且您可能能够获得解决该问题的帮助。

    编辑:

    您确定使用该参数调用该方法吗?如果你使用会发生什么

     service.Stub(r => r.GetUser(Arg<String>.Is.Anything)).Return(new LoginUser());
    

    你有退货吗?

    如果您设置一个期望值而不是简单地存根然后验证期望值,那会不会给您提供更多信息?

    service.Expect(r => r.GetUser(Arg<String>.Is.Anything)).Return(new LoginUser());
    service.VerifyAllExpectations();
    

    EDIT2:

    好的,我做了一些测试,这似乎是您创建存根对象的方式。我假设您使用的方式是旧样式,而您需要将其用于新样式:

    service = MockRepository.GenerateStub<IMembershipService>();
    

    当我更改为这个时,我可以运行测试并让它们通过。我不确定使用静态方法生成存根和使用测试MockRepository 实例之间的确切区别。也许其他人可以解释它的来龙去脉。

    为了完整起见,这里是我运行的代码:

    [TestFixture]
    public class AuthorizationTest
        {
        private IMembershipService service;
    
        [SetUp]
        public void SetUp()
            {
            service = MockRepository.GenerateStub<IMembershipService>();
            service.Stub(r => r.GetUser("dummyName")).Return(new LoginUser()); 
            }
    
        [Test]
        public void GetCurrentUser_UserIsAuthenticated_ReturnsCurrentUser()
            {
            var authStub = new AuthorizationStub_SetCurrentUserAuthenticated(service, true);
    
            LoginUser u = authStub.GetCurrentUser();
            Assert.That(u != null);
            }
    
        [TearDown]
        public void TearDown()
            {
            service = null;
            }
        }
    
    public class AuthorizationStub_SetCurrentUserAuthenticated
        {
        private readonly IMembershipService m_service;
        private readonly bool m_b;
    
        public AuthorizationStub_SetCurrentUserAuthenticated (IMembershipService service, bool b)
            {
            m_service = service;
            m_b = b;
            }
    
        public LoginUser GetCurrentUser ()
            {
            return m_service.GetUser ("dummyName");
            }
        }
    
    public interface IMembershipService
        {
        bool ChangePassword(string username, string oldPassword, string newPassword);
        LoginUser GetUser(string username);
        LoginUser GetUser(object providerUserKey);
        string ResetPassword(string username);
        bool ValidateUser(string username, string password);
        }
    
    public class LoginUser
        {
        }
    

    【讨论】:

    • 感谢您的示例。奇怪的是,除非存在带有记录和最后调用的存根,否则测试仍然失败。当那个存根在那里并且我还包括你的 service.Expect 和 service.VerifyAllExpectations 它通过了。如果我将记录和 lastcall 存根与您的存根示例交换,它将失败。
    • 我发布了我的界面,也许问题是由于过载和存根选择了错误的方法?
    • 不行,重命名了其中一种方法,问题依旧。
    • 感谢您的帮助,感谢您的努力,我将为您提供一些不错的东西...+125(24 小时内)。仍然想知道为什么实例方法会产生如此大的差异,但无论如何......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 2011-08-02
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多