在同一个类中模拟一个方法

时间:2014-03-05 23:24:39

标签: c# unit-testing moq

以下是我对调查猴子api oauth令牌的webRequest Post方法的实现。我正在为下面的代码编写单元测试。

public string GetSurveyMonkeyToken(string apiKey, string clientSecret, string tempAuthCode, string redirectUri, string clientId)
{
    if (!VerifyRedirectedTempCode(tempAuthCode))//this method is in the same class which checks the temp code valid(true) or not(false)
    {
        return null;
    }
    else
    {
        WebRequestForTokenOfSurveyMonkey = GetWebRequestForHttpPostOfSurveyMonkeyToken(apiKey, clientSecret, tempAuthCode, redirectUri, clientId);
        using (HttpWebResponse responseHttpPostForToken = GetResponse(WebRequestForTokenOfSurveyMonkey))//Getresponse method is in the same class which returns this (HttpWebResponse)webRequestObject.GetResponse()
        {
            string tokenJson = new StreamReader(responseHttpPostForToken.GetResponseStream()).ReadToEnd();
            AccessToken accesstokenObj = JsonConvert.DeserializeObject<AccessToken>(tokenJson);
            string accessTokenSurvey = accesstokenObj.access_token.ToString();
            return (accesstokenObj.access_token.ToString());
        }
    }
}

现在上面的代码工作正常,但是我在编写单元测试时遇到问题。对我们来说是单元测试,一个测试我模拟我的方法返回false工作正常它返回null。

[Test]
public void GetSurveyMonkeyTokenTestWithValidTempCode()
{
    var mockedSurveyMonkeyToken = new Moq.Mock<SurveyMonkeyAPIService>();
    mockedSurveyMonkeyToken.CallBase = true;
    mockedSurveyMonkeyToken.Setup(a => a.VerifyRedirectedTempCode(It.IsAny<string>())).Returns(true);
    var mockRequest = mockedSurveyMonkeyToken.Object.GetWebRequestForHttpPostOfSurveyMonkeyToken(TestData.TestData.SampleApiKey, TestData.TestData.SampleClientSecret, TestData.TestData.SampleTempAuthCode, TestData.TestData.SampleRedirectUri, TestData.TestData.SampleClientId);
    mockedSurveyMonkeyToken.VerifyAll();
}

此测试方法的错误是 Moq.MockVerificationException:以下设置未匹配: SurveyMonkeyAPIService a =&gt; a.VerifyRedirectedTempCode(It.IsAny())

我的测试中出现了什么问题。我正确地编写了测试方法。我是第一次编写httpwebrequest测试方法。

2 个答案:

答案 0 :(得分:3)

我认为你可能错误地应用了Mocking的概念。

Mocking的目的应该用于模拟被测试类的 依赖

不幸的是,您似乎正在做的是模拟正在测试的类的方法。当你刚开始时,这是一个容易犯的错误。但是,这样做会破坏单元测试的整个目的,因为您的目标应该是独立测试类的功能。如果你模拟了类的方法,你将有效地替换你试图测试的实现。

在查看单元测试时,您会发现整个测试围绕模拟var mockedSurveyMonkeyToken = new Moq.Mock<SurveyMonkeyAPIService>();进行。

您要做的是确定您的类的依赖关系,然后将其模拟出来,以便您可以在测试类的公共方法时控制它们执行的操作。

如果SurveyMonkeyAPIService是依赖项,那么您将该模拟传递给被测试的类。 (例如var cut = new MyClassUnderTest(surveyMonkeyAPIServiceMock)

但是,如果我怀疑SurveyMonkeyAPIService是被测试的类,那么您将需要在测试中创建此类的实例并传入任何依赖项的模拟。我认为你的依赖是HttpWebResponse webRequestObject

您的测试将具有以下内容:

var sm = new SurveyMonkeyAPIService(webRequestObjectMock); //create the class under test. Arrange
sm.GetSurveyMonkeyToken(...); //exercise the class under test. Act
webRequestObjectMock.Verify(...); //verify that the mock was exercised as expected. Assert

注意:安排,行动,断言是Triple A单元测试的三个步骤......

有关如何模拟HttpWebResponse依赖关系的示例,请参阅this question

答案 1 :(得分:1)

我同意mezoid你的测试非常不正统。您的测试失败的原因是您直接调用GetWebRequestForHttpPostOfSurveyMonkeyToken方法,而不是GetSurveyMonkeyToken方法。 GetWebRequestForHttpPostOfSurveyMonkeyToken可能不会致电VerifyRedirectedTempCode,因为您已在GetSurveyMonkeyToken中致电{1}}。

要让测试通过,可能您可以更改行

var mockRequest = mockedSurveyMonkeyToken.Object.GetWebRequestForHttpPostOfSurveyMonkeyToken(TestData.TestData.SampleApiKey, TestData.TestData.SampleClientSecret, TestData.TestData.SampleTempAuthCode, TestData.TestData.SampleRedirectUri, TestData.TestData.SampleClientId);

var mockRequest = mockedSurveyMonkeyToken.Object.GetSurveyMonkeyToken(TestData.TestData.SampleApiKey, TestData.TestData.SampleClientSecret, TestData.TestData.SampleTempAuthCode, TestData.TestData.SampleRedirectUri, TestData.TestData.SampleClientId);

但我会考虑重新设计你的应用程序,以分离出你想要测试的单元。也许您应该向codereview stackexchange网站发布一个问题。