Unit Test FAQ RRS feed

  • General discussion

  • Q: How do I see non-public stuff in a unit test?

    Suppose we have a class like the following:


    Public Class ToTest

        Sub SetValue(y as Integer)

            x = y

        End Sub

        Private x As Integer

    End Class


    We would like to call SetValue and verify that 'x' gets set.


    OK.  Right click on SetValue to create a test.  Create a new VB Test (or put it into an existing VB Test).


    In the generated test, let's set the initialization of 'y' to 3.


    Go back to your original code, Right Click on SetValue again, but this time, select the Create Private Accessor command, inserting the accessor into your VB Test Project.


    What you want to do is use an accessor to 'wrap' you ToTest object so it can pull private data out of it.  This is done follows:


      Dim privTarget As VBClassLib_ToTestAccessor = New VBClassLib_ToTestAccessor(target)


    The 'VBClassLib_ToTestAccessor' type I 'discovered' by looking in Class View.  I could also have just looked at VSCodeGenAccessor.vb - but this file is really hard to read.


    Now you can replace the Assert.Inconclusive at the bottom of the Test Method with:


      Assert.AreEqual(3, privTarget.x, "x needs to be 3")


    And run the test.

    The final code should look like:



        '''A test for SetValue(ByVal Integer)


        <TestMethod()> _

        Public Sub SetValueTest()

            Dim target As ToTest = New ToTest


            Dim y As Integer = 3




            Dim privTarget As VBClassLib_ToTestAccessor = New VBClassLib_ToTestAccessor(target)

            Assert.AreEqual(3, privTarget.x, "x needs to be 3")

        End Sub


    Q: How can I test native code (non-.NET code) with Team System?

    The test framework supports C++ Unit Test projects that can be modified to support this scenario, with some caveats.

    1. Bring up the project properties and change the General Setting for CLR type from '/clr:safe' to just be '/clr'.  This will allow native code to be mixed into the project.
    2. If your test project will contain a DllMain, you should consider putting #pragma unmanaged around it.  There are issues with managed code in DllMain.
    3. If your test class will be called MyTestClass.  In the code you will be testing, if you wish to have access to the private data, add MyTestClass as a friend in the class definition.  This can be a little tricky if your target code will never be mixed mode.  Consider something like this in a common header file:
      #ifdef UNIT_TESTING
        #define UNITTESTFRIEND(c) friend ref class c
        #define UNITTESTFRIEND(c)
    4. Make your test project dependant on your native project (right click the solution and select Project Dependancies).
    5. #include whatever files you need for testing the code you want.
    6. If your target project is a static library, everything is good at this point, just link it to the test project.
    7. If your target is not a static library, you have two choices.  Link the object files from the target project, or refactor your native project into two projects where one is a static library and the other is of the original type and just contains the entrypoint stubs.
    8. You will have the most luck using Assert::IsTrue(expression, comment) to verify your results.  This enables C++ to do expression evaluation.  If you try to use AreEquals() and friends, it will expect 'objects' to be passed in, and this is often not intuitive for native code.
    9. VERY IMPORTANT: Add any native DLLs that you require that are not on the system path to the TestRunConfiguration Deployment Items.  VSTS Tests run in an isolated directory and non-path'd native dll's need to be registered with the depoyment items.  You can also use the [DeploymentItem()] attribute on your test.  If you get a failure saying that your test assembly could not be found or loaded, this is most likely the problem.
    10. If you have any static construction (global objects, etc...) that end up throwing an exception at startup - you will want to attach a debugger at the point you get a message box saying vstesthost.exe has terminated unexpectedly.  Attach it to vstesthost.exe and see what the call stack shows.  This can also happen if you allow a Structured Exception, or C++ exception to bubble out of your test code. 
    11. Do not Use [ExpectedException] on a test for C++ exceptions.
    12. Read to understand what you can not do in /clr compiled C++ code.



    Friday, January 12, 2007 4:58 PM