locked
How to call ramda expression in unit test? RRS feed

  • Question

  • ------------------------------------------------
    public class Program
        {       
            private void A()
            {
                SystemBit temp = new SystemBit();
                temp.req = () =>
                    {
                    };
            }
        }
    
    
    ------------------------------------------------
    
    [TestMethod]
            public void TestMethod1()
            {
                Program test_var = new Program();
    
                var temp_obj = new PrivateObject(test_var);
                temp_obj.Invoke("A");           
            }
    

    How to call explicitly Temp.req = () => {}; in ramda expression(picture1) to TestMethod1(picture2) when unit testing is performed for private method A in Program class?


    Monday, January 9, 2017 8:53 AM

All replies

  • Fakes are available in Visual Studio Enterprise.

    Monday, January 9, 2017 9:49 PM
  • Hi Jinsub39,

    Thank you for posting here.

    According to your question is more related to Unit Test, I will move it to Visual Studio Unit Test forum for suitable support.

    The Visual C# discuss and ask the C# programming language, IDE, libraries, samples and tools.

    If you have some grammar or code errors, please feel free to contact us. We will try our best to give you a solution.

    Thanks for your understanding and cooperation.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, January 10, 2017 6:55 AM
  • Hi Jinsub39,

    >>when unit testing is performed for private method A in Program class?

    During the unit test, we do not suggest to test the private method, please read the following thread:

    http://stackoverflow.com/questions/250692/how-do-you-unit-test-private-methods

    >> How to call explicitly Temp.req = () => {};

    In Test Method, you could call the test method A to see whether this lambda express could be run (change private method to public method). In my side, I add a lambda in one method, and in test method I could run it without any problems.

    Sincerely,

    Oscar


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, January 11, 2017 7:53 AM
  • Fakes are available in Visual Studio Enterprise.

    Just to clarify my previous answer, this has nothing to do with the method being private, but instead has to do with the fact that you are testing at a unit granularity finer than methods.  You are hoping to get at expressions within the method.  As I hinted at before, with a Fake, you can replace the implementation of SystemBit, and therefore intercept the assignment to the .req property in your fake, and then your test can call the lambda directly to test its functionality.

    Without Enterprise edition, you will have to design your program to support being testable at the granularity of the lambda function.  This means that if you want to test the lambda function then you will need to provide a mechanism by which you pass in the object that consumes the lambda function, and design for a testable interface through which you can replace the real SystemBit with a fake SystemBit when testing the A method.

    example of a testable interface:

        public interface ISystemBit
        {
            Action req { get; set; }
        }

    Example of how A would have to change to use a testable interface.  You would pass in a new SystemBit when calling A rather than A create its own.  That way you can provide a fake during testing.

          private void A( ISystemBit systemBit )
            {
                systemBit.req = () =>
                    {
                    };
            }

    Now, I notice that your lambda signature is a function taking no arguments, returning no value...  That's not a testable API either, but I assume your real situation is more complex so I'll proceed.  I suppose minimally you could simply test that the lambda does not throw an exception -- that's better than nothing.

    Also, be very careful that a lambda function is a closure, and may be written to depend on variables that have context only during the execution of A().  Therefore any testing you do on it will have to occur within a callback during the execution of A().

    Your test might look like this (see below).  Here, I call into the lambda to test it when .req is assigned a value.

        [TestClass]
        public class UnitTest1
        {
            class FakeSystemBit : ISystemBit
            {
                /// <summary>
                /// Constructor for a FakeSystemBit
                /// </summary>
                /// <param name="callback">A callback that gets called with the value of .req when assigned</param>
                public FakeSystemBit( Action<Action> callback )
                {
                    _callback = callback;
                }
                Action<Action> _callback;
                public Action req
                {
                    get
                    {
                        throw new NotImplementedException();
                    }
    
                    set
                    {
                        _callback( value );
                    }
                }
            }
    
            [TestMethod]
            public void TestMethod2()
            {
                Program test_var = new Program();
                FakeSystemBit fake = new FakeSystemBit( delegate( Action fn )
                {
                    // Write your test here.
                    // e.g.: call the fn and hope for no exceptions.
                    fn();
                } );
                var temp_obj = new PrivateObject( test_var );
                temp_obj.Invoke( "A", fake );
            }
        }


    • Edited by Wyck Wednesday, January 11, 2017 3:45 PM oops missed one important parameter in the fake call
    • Proposed as answer by Oscar_Wu Monday, January 23, 2017 7:28 AM
    Wednesday, January 11, 2017 3:43 PM
  • Wyck, Thanks for your answer.

    I followed Your answer,

    and It causes an error.

    Because, A() method don't have parameter.

    Therefore, System.MissingMethodException is occurred.


    • Edited by Jinsub39 Thursday, January 12, 2017 11:59 AM
    Thursday, January 12, 2017 11:58 AM
  • Wyck, Thanks for your answer.

    I followed Your answer,

    and It causes an error.

    Because, A() method don't have parameter.

    Therefore, System.MissingMethodException is occurred.


    Yes, this will require some redesign.  If you read my previous comment you'll see that I mentioned that you would have to change A() like this:

     private void A( ISystemBit systemBit )
            {
                systemBit.req = () =>
                    {
                    };
            }

    And then callers of A will have to call A(new SystemBit())

    The unit test will have to call A and pass in the FakeSystemBit from the test.

    (Side note: If you use Fakes from Visual Studio Enterprise, you can inject the Fake rather than hand crafting it.)


    • Edited by Wyck Thursday, January 12, 2017 3:34 PM
    Thursday, January 12, 2017 3:33 PM
  • Wyck, Thanks for your answer.

    I followed Your answer,

    and It causes an error.

    Because, A() method don't have parameter.

    Therefore, System.MissingMethodException is occurred.


    Yes, this will require some redesign.  If you read my previous comment you'll see that I mentioned that you would have to change A() like this:

     private void A( ISystemBit systemBit )
            {
                systemBit.req = () =>
                    {
                    };
            }

    And then callers of A will have to call A(new SystemBit())

    The unit test will have to call A and pass in the FakeSystemBit from the test.

    (Side note: If you use Fakes from Visual Studio Enterprise, you can inject the Fake rather than hand crafting it.)


    I use visual studio 2012 ultimate.

    And I have limitations.

    I don't have to modify test class.

    so I have to perform current feature.

    Friday, January 13, 2017 1:47 AM
  • Hi Jinsub39,

    I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay. Appreciate your patience.
    Thanks for your understanding!

    Sincerely,

    Oscar


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, January 16, 2017 9:49 AM
  • I don't have to modify test class.

    so I have to perform current feature.

    "I have to perform current feature" doesn't make sense to me.  Can you say it with different words please?

    You can't unit test a lambda expression unless you make it part of your API.  If you think about it, with things like LINQ, lambda expressions may not even turn out to be functions.

    Your unit test for "A" should pass if "A" is implemented correctly, and fail if "A" is implemented incorrectly.

    But if someone write changes the implementation of A so that it doesn't use a lambda function, why should a unit test break?  Why require that the implementation of A uses a lambda function?

    Are you testing at the right granularity?  Are you testing contracts between other components at the method level, or are you just trying to manufacture unit tests after you've designed the implementation.  Your unit tests should allow for valid code changes.  And I propose that providing an implementation of A that doesn't use a lambda is valid.

    It seems that you want to unit test the lambda expression you wrote in your implementation of A and you want it to be somehow exposed for you to call independently.  The only way to do this that makes sense to me is to intercept it by pretending to be the method to which the lambda expression was passed.

    Other approaches would involve trying to locate the anonymous method via reflection (if one were even created).  But I don't think this is a good strategy.

    Monday, January 16, 2017 2:05 PM
  • I don't have to modify test class.

    so I have to perform current feature.

    "I have to perform current feature" doesn't make sense to me.  Can you say it with different words please?

    You can't unit test a lambda expression unless you make it part of your API.  If you think about it, with things like LINQ, lambda expressions may not even turn out to be functions.

    Your unit test for "A" should pass if "A" is implemented correctly, and fail if "A" is implemented incorrectly.

    But if someone write changes the implementation of A so that it doesn't use a lambda function, why should a unit test break?  Why require that the implementation of A uses a lambda function?

    Are you testing at the right granularity?  Are you testing contracts between other components at the method level, or are you just trying to manufacture unit tests after you've designed the implementation.  Your unit tests should allow for valid code changes.  And I propose that providing an implementation of A that doesn't use a lambda is valid.

    It seems that you want to unit test the lambda expression you wrote in your implementation of A and you want it to be somehow exposed for you to call independently.  The only way to do this that makes sense to me is to intercept it by pretending to be the method to which the lambda expression was passed.

    Other approaches would involve trying to locate the anonymous method via reflection (if one were even created).  But I don't think this is a good strategy.

    The original code that includes method A has already been completed.

    so it is impossible to modify.

    And I want to get code coverage(block coverage).

    My goal is to achieve 100 % code coverage.

    Wednesday, January 18, 2017 8:53 AM
  • Hi Jinsub39,

    If your original question has been resolved, please remember to mark useful answer as answer, which could be helpful for others who has the same issue as yours.

    >>My goal is to achieve 100 % code coverage.

    Please check which code block could not be run. Right-click the test method choose Analyze Coded Coverage for Selected Tests in Test Explorer panel.

    The MSDN forum has itself policy, we cannot post several question in the same thread. So I would you suggest you re-post new thread about your issue that you encountered. Since one thread for one issue, would you please open a new case for this new issue? In this way, our discussion here will not deviate too much from the original issue. This will make answer searching in the forum easier and be beneficial to other community members as well.

    Sincerely,

    Oscar


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, January 18, 2017 9:42 AM
  • The original code that includes method A has already been completed.

    so it is impossible to modify.

    What's the point of writing unit tests for code you didn't write?  What will you do when the unit test fails?  If you can't modify `A` to fix it, then all you can do is reject using `A` completely.

    And I want to get code coverage(block coverage).

    My goal is to achieve 100 % code coverage.

    You will get code coverage for the lambda even if you don't invoke it directly from the test.  Just call A and it will execute.
    Wednesday, January 18, 2017 4:02 PM
  • The original code that includes method A has already been completed.

    so it is impossible to modify.

    What's the point of writing unit tests for code you didn't write?  What will you do when the unit test fails?  If you can't modify `A` to fix it, then all you can do is reject using `A` completely.

    And I want to get code coverage(block coverage).

    My goal is to achieve 100 % code coverage.

    You will get code coverage for the lambda even if you don't invoke it directly from the test.  Just call A and it will execute.

    I already called method A. but, I didn't get code coverage for lamda. The lamda didn't execute.

    so I posted this question. I want to know how to call lamda directly in unit test project.


    • Edited by Jinsub39 Thursday, January 19, 2017 12:47 AM
    Thursday, January 19, 2017 12:46 AM
  • Hi Jinsub,

    I have a doubt about your question, lamda just a line code, we could call a method from another class, but how to call a line code from another class?

    Sincerely,

    Oscar


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Oscar_Wu Friday, January 20, 2017 7:43 AM
    Friday, January 20, 2017 7:43 AM
  • Maybe you should share the original code.  Lambda expressions don't necessarily become functions.  Such as when you use LINQ to SQL, where the lambda expression may be transformed into SQL and executed on the server side, in applicable cases.
    Friday, January 20, 2017 6:28 PM
  • Maybe you should share the original code.  Lambda expressions don't necessarily become functions.  Such as when you use LINQ to SQL, where the lambda expression may be transformed into SQL and executed on the server side, in applicable cases.

    The rambda expression is a function to initialize.

    and I don't have to share original code.

    Wednesday, February 8, 2017 7:48 AM
  • I already called method A. but, I didn't get code coverage for lamda. The lamda didn't execute.

    so I posted this question. I want to know how to call lamda directly in unit test project.


    This is why I wanted to know what the lambda function was for in your original code or to see the actual code you are trying to test.  If you called A and the lambda function didn't execute then it's because SystemBit didn't call it -- or more importantly, 'A' didn't cause 'SystemBit' to call its 'req' function.

    All 'A' does is assign .req a value.  It doesn't ask the SystemBit to do anything.  .req would have to be a property setter that called code to execute the value it was assigned.  I wouldn't expect it to (in typical use of a property setter).  Now if there were another method of SystemBit that you need to call, like maybe something called "run" or "exec" or something, then maybe that function would call the lambda function you assigned to .req.

    But I don't even know what your SystemBit class is.  So what is it?


    • Edited by Wyck Wednesday, February 8, 2017 9:20 PM
    Wednesday, February 8, 2017 9:20 PM