Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throwing an exception nulls any out parameters #342

Closed
JefWight opened this issue May 10, 2017 · 3 comments
Closed

Throwing an exception nulls any out parameters #342

JefWight opened this issue May 10, 2017 · 3 comments

Comments

@JefWight
Copy link

I'm trying to abstract making web requests. I've written an interface to replace both the Request and Response portions. To enable the most complete support for mocking, the design is such that void GetResponse(out IResponse response); is expected to set the response value even on WebException (if the exception has a Response property that's an HttpWebResponse). This allows me to to use the interface to extract info about the response even in a WebException.

In my test code, I've tried:

ISetup<IRequestMessage<IResponseMessage>> getResponse = request.Setup(r => r.GetResponse(out response));
getResponse.Throws(exceptionToThrow);

I've also tried approximately what I found on stack overflow by attempting to set a "callback" that would explicitly set the out parameter then throw:

public delegate void OutAction(out IResponseMessage response);
private static void SetOutThenThrow(this ICallback mock, IResponseMessage response, Exception exceptionToThrow)
{
    OutAction foo = (out IResponseMessage r) =>
        {
            r = response;
            throw exceptionToThrow;
        };

    mock.GetType()
        .Assembly.GetType("Moq.MethodCall")
        .InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock, new[] { foo });
}

While both approaches throw an exception as expected, neither of these approaches result in the out parameter being set in the calling code.

I suspect this has something to do with the way the reflection code is executing.

@stakx
Copy link
Contributor

stakx commented Jun 25, 2017

Hi @JefWight, thanks for the report. Could you please post a brief but complete code example that reproduces this issue? (Please try to avoid doing reflection over Moq internals in the repro code. Try to show what you're attempting to do using the public API.) Thanks!

@JeffyW
Copy link

JeffyW commented Jun 26, 2017

Sorry, it looks like this was just a bug in the version our test tools was using (4.0.10827), but when I create a test project and use the latest version, it works correctly. For reference, here's the code that doesn't work in 4.0.10827:

namespace UnitTest
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestOutParameterWorksWithThrows()
        {
            var mockTest = new Mock<ITest>();
            var test = mockTest.Object;

            var outString = "test";
            var tryDoSomething = mockTest.Setup(t => t.TryDoSomething(out outString));

            string newOutString = null;
            tryDoSomething.Throws<TimeoutException>();
            try
            {
                var result = test.TryDoSomething(out newOutString);
            }
            catch (TimeoutException)
            {
            }

            Assert.AreEqual(outString, newOutString);
        }

        public interface ITest
        {
            bool TryDoSomething(out string value);
        }
    }
}

Feel free to close this out.

@stakx
Copy link
Contributor

stakx commented Jun 26, 2017

Thanks for replying. Since we're not fixing old versions :) I'll close this.

@stakx stakx closed this as completed Jun 26, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants