更改模拟的getResponse .net

时间:2016-02-29 10:14:26

标签: c# unit-testing moq

我有一个测试,可以从端点获取某些设备状态。我有反应嘲笑并正确获取信息。我想要实现的测试必须获取此信息,并在一段时间后再次获取该信息并检查是否与抛出事件不同。问题是我无法在测试中更改模拟的响应。这就是我的尝试。

模拟WebRequest的实现。

class TestWebRequestCreate : IWebRequestCreate
{

    public TestWebRequest testWebRequest { get; set; }

    public WebRequest Create(Uri uri)
    {
        WebRequest webRequest;
        if (testWebRequest == null)
        {
            webRequest = new TestWebRequest(HttpStatusCode.OK, "Testing response");
        }
        else
        {
            webRequest = testWebRequest;
        }
        return webRequest;
    }
}

class TestWebRequest : WebRequest
{
    public HttpStatusCode httpStatusCode { get; set; }
    public Stream responseMessage;

    /// <summary>
    ///  Initialize a new instance of <see cref="TestWebRequest"/>
    ///  with the response to return
    /// </summary>
    public TestWebRequest(HttpStatusCode httpStatusCode, string responseMessage)
    {
        this.httpStatusCode = httpStatusCode;
        this.responseMessage = StreamFromString(responseMessage);

    }

    public override WebResponse GetResponse()
    {
        MemoryStream responseCopy = new MemoryStream();
        //Stream responseCopy = new MemoryStream();
        responseMessage.Position = 0;
        responseMessage.CopyTo(responseCopy);
        //Reset position after reading Streams
        responseCopy.Position = 0;
        Mock<HttpWebResponse> mockHttpWebResponse = new Mock<HttpWebResponse>();
        mockHttpWebResponse.Setup(r => r.StatusCode).Returns(httpStatusCode);
        mockHttpWebResponse.Setup(r => r.GetResponseStream()).Returns(responseCopy);
        return mockHttpWebResponse.Object;
    }  

在我的测试之后,我这样做:

        public void DeviceChangedEvent_WhenDeviceHaveChanged_EventIsThrown()
    {
        string uri = new UriBuilder(TESTHOSTPREFFIX, TESTCORRECTHOST, TESTPORT, TESTDEVICEENDPOINT).ToString();
        bool wasThrown = false;
        m_deviceRetriever.Init(m_serviceProvider);
        m_deviceRetriever.Start();
        m_deviceRetriever.DeviceChangeEvent += (DeviceRetrieverOnDeviceChangeEvent, args) =>
        {
            wasThrown = true;
        };

        Thread.Sleep(5000);

        //Change device XML to simulate the change
        var namespaceManager = new XmlNamespaceManager(m_correctMockedXmlDevice.NameTable);
        namespaceManager.AddNamespace("ps", "http://www.hp.com/ps/fall15");
        XmlNode printheadIdNode = m_correctMockedXmlDevices.SelectSingleNode("/ps:DevicesStatus/DeviceSlotCollection/DeviceSlot/SlotId", namespaceManager);
        deviceIdNode.InnerText = "Changed";
        m_testWebRequestCreateCorrectDevices = null;
        m_testWebRequestCreateCorrectDevices = new TestWebRequestCreate
        {
            testWebRequest = new TestWebRequest(HttpStatusCode.OK, m_correctMockedXmlDevices.InnerXml)
        };

        Thread.Sleep(5000);

        //We give some time to get the new state of printheads
        Assert.IsTrue(wasThrown);
    }
}

在测试之前我准备创建这个

    private void CreateCorrectDevicesMockEndpoint()
    {
        string uri = new UriBuilder(TESTHOSTPREFFIX, TESTCORRECTHOST, TESTPORT, TESTPRINTHEADSENDPOINT).ToString();
        m_testWebRequestCreateCorrectDevices = new TestWebRequestCreate();
        m_correctMockedXmlDevices = new XmlDocument();
        m_correctMockedXmlDevices.Load("pathToXMLFile");
        m_testWebRequestCreateCorrectDevices.testWebRequest = new TestWebRequest(HttpStatusCode.OK, m_correctMockedXmlPrintheads.InnerXml);
        WebRequest.RegisterPrefix(uri, m_testWebRequestCreateCorrectDevices);
    }

编辑: 我的测试设置是初始化所有必要的依赖项。

    public void SetUp()
    {
        m_serviceProvider = new ServiceProvider();

        m_serviceProvider.Add<ILogger>(new Mock<ILogger>().Object);

        m_deviceRetriever = new DeviceRetriever();

        m_connectivitySettings = new ConnectivitySettings() { IpAddress = TESTCORRECTHOST };
        m_serviceProvider.Add<ConnectivitySettings>(m_connectivitySettings);

        CreateCorrectDevicesMockEndpoint();
    }

我没有收到任何错误,问题是我的mock返回的XML没有改变。谢谢你的帮助!

1 个答案:

答案 0 :(得分:1)

正如我在评论中所说,我相信你的问题出现在你没有向我们展示的代码中。您设置的模拟工作正常,但它依赖于您GetResponse的正确实例上的TestWebRequest来电。我的信念是,无论您是在进行轮询,您都不会更新轮询器正在使用的TestWebRequestCreate实例,因此它只是使用原始模拟创建TestWebRequest设置的另一个实例。下面是一个示例,完整的测试,说明您的模拟工作,可以从不同的线程访问并按预期工作。

bool wasThrown = false;
IWebRequestCreate m_testWebRequestCreateCorrectDevices = null;

[TestMethod]
public void TestThreadedWebRequest()
{
    const string errorResponse = "Some Error Text";
    m_testWebRequestCreateCorrectDevices = new TestWebRequestCreate();
    var uri = new Uri(@"http:\\www.stackoverflow.com");
    wasThrown = false;

    var thread = new System.Threading.Thread(() =>
        {
            while (true)
            {
                var creator = m_testWebRequestCreateCorrectDevices;
                if (creator != null)
                {
                    var message = creator.Create(uri); 
                    var response = new StreamReader(message.GetResponse()
                                                      .GetResponseStream()).ReadToEnd();
                    if (response == errorResponse)
                    {
                        wasThrown = true;
                        break;
                     }
                }
                System.Threading.Thread.Sleep(500);
            }
        });

    thread.Start();

    System.Threading.Thread.Sleep(5000);
    Assert.AreEqual(false, wasThrown);


    m_testWebRequestCreateCorrectDevices = null;
    m_testWebRequestCreateCorrectDevices = new TestWebRequestCreate
    {
        testWebRequest = new TestWebRequest(HttpStatusCode.OK, errorResponse)
    };

    System.Threading.Thread.Sleep(5000);

    Assert.AreEqual(true, wasThrown);

    if (!thread.Join(1000))
    {
        thread.Abort();
    }
}

请注意,在现有代码中,您将m_testWebRequestCreateCorrectDevices设置为创建正确模拟响应的新邮件创建者的实例。除非您的生产代码引用此变量(在我上面的示例中就是这种情况),否则这可能不够。