Tutorial 05 01 Unit Testing Generated OData Services - Synergex/HarmonyCore GitHub Wiki

Harmony Core Logo

Tutorial 5: Unit Testing Generated OData Services

In this tutorial, you will add, generate, configure, and run unit tests for generated OData controllers and endpoints.

Before you begin, you must have an existing Harmony Core solution with generated OData services from Tutorial 2: Building a Service From Scratch. If your solution also includes custom authentication from Authentication via Custom Code, this will still apply.

Add and Configure Test Projects

You will add two projects: Services.Test, the generated unit test project and test host environment, and Services.Test.GenerateValues, a helper project that reads data and generates or updates test constants used by Services.Test.

  1. Open your existing Harmony Core solution in Visual Studio and verify that it builds without errors.

  2. In Visual Studio, select Services.Host in Solution Explorer, and then select Tools > Command Prompt (x64).

  3. At the command prompt, navigate to your solution root folder (the folder that contains your .sln file and Common.props). Then set SolutionDir to that folder:

    set SolutionDir=%CD%\
    

    Note the trailing backslash, which is important.

  4. Install or update the Harmony Core project templates:

    dotnet new install Harmony.Core.ProjectTemplates
    
  5. Make sure the harmonycore-ut and harmonycore-utg templates are in the list of templates output by the previous command.

  6. Create the Services.Test project:

    dotnet new harmonycore-ut -o Services.Test
    
  7. Create the Services.Test.GenerateValues project:

    dotnet new harmonycore-utg -o Services.Test.GenerateValues
    
  8. In Visual Studio, add both projects to the solution with Add > Existing Project:

    • Services.Test\Services.Test.synproj

    • Services.Test.GenerateValues\Services.Test.GenerateValues.synproj

  9. Save your changes by selecting File > Save All.

Run the Project Upgrade Tool

After adding the two template-based projects, align package and template versions across the solution.

  1. Switch back to the command prompt and run these commands:

    dotnet tool update -g Harmony.Core.CliTool
    harmonycore upgrade-latest
    
  2. When prompted after the second command, type YES to continue.

  3. Return to Visual Studio. If prompted to reload modified projects, click Reload All.

Verify Project References and Package Versions

Review the following project files and add or update entries only if they are missing or mismatched.

  1. In Services.synproj, confirm that the following package reference exists with the specified version:

    <PackageReference Include="Swashbuckle.AspNetCore">
      <Version>6.9.0</Version>
    </PackageReference>
    
  2. In Services.Test.synproj, confirm that the following exist with the specified versions:

    <PackageReference Include="Microsoft.OData.Core">
      <Version>8.4.2</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.OData.Edm">
      <Version>8.4.2</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.Spatial">
      <Version>8.4.2</Version>
    </PackageReference>
    

    If they don't exist, add them after the Microsoft.AspNetCore.OData package reference. These explicit OData package references prevent assembly/version resolution conflicts at build and runtime.

  3. In Services.Test.GenerateValues.synproj, confirm that the following exists with the specified version:

    <PackageReference Include="BitFaster.Caching">
      <Version>2.5.4</Version>
    </PackageReference>
    

    If this doesn't already exist, add it in the first ItemGroup. This setting avoids older transitive BitFaster.Caching versions that can cause runtime failures in Harmony Core file I/O components.

  4. Rebuild the solution (Build > Rebuild Solution).

    • You may see this error: "%DBL-F-NULPR, No primary files specified" for Services.Test. Ignore it at this point, but resolve any other build errors before continuing.

    • If you get warnings about version resolution for package references, clean and rebuild Services.Test.GenerateValues, clean and rebuild Services.Test, and then rebuild the solution.

Enable Unit Test Code Generation

Now enable unit-test generation in Harmony Core so that test scaffolding is included in the next regen.

  1. Launch the Harmony Core CLI Tool GUI from the solution root:

    harmonycore gui
    
  2. In the OData tab of the CLI Tool, set Enable unit tests to Yes. (Double-click Enable unit tests and then, in the Enter new value screen, click the diamond icon to the right of Enable unit tests. The diamond will change to a checkmark. Click OK.)

  3. Save settings (File > Save).

Generate Code

With unit tests enabled, regenerate code so that the test project will have the required generated files.

  1. In the CLI Tool, run CodeGen > Regen. A window will open showing the files generated for the Enable unit tests option.

What Gets Generated

When unit tests are enabled, code generation updates Services.Test with files such as:

  • SelfHost.dbl
  • UnitTestEnvironment.dbl
  • TestConstants.Properties.dbl
  • DataGenerators\*.dbl
  • Models\*.dbl
  • UnitTests\*.dbl

The generated unit test methods use HttpClient and call your OData endpoints the same way an external client does.

Add the New Files

After regeneration, make sure all newly created files are included in the Visual Studio projects.

  1. Do one of the following:
  • In the CLI Tool, select CodeGen > Sync VS to add the newly generated files.
  • In Visual Studio, use Add Existing Item to add the files that were generated for Services.Test (listed above).
  1. Quit the CLI Tool.

Build the Test Projects

Before generating constants or running tests, verify both test-related projects compile cleanly.

  1. Build Services.Test in Visual Studio and verify there are no errors.

  2. Build Services.Test.GenerateValues and verify there are no errors.

Generate Test Constants and Run Tests

Next, create the test constants from your sample data and execute the generated test suite. The Services.Test.GenerateValues helper project includes GenerateTestValues.dbl, which reads test data files and creates or updates Services.Test\TestConstants.Values.json.

  1. From the solution root, generate test constants by running the following at the command prompt:

    dotnet run --project Services.Test.GenerateValues\Services.Test.GenerateValues.synproj
    

    This command creates or updates Services.Test\TestConstants.Values.json.

    You should see output similar to this (though "No JSON file found..." message appears only on the first run):

    Processing file DAT:customers.ism
    - Opening DAT:customers.ism...
    - Counting records...
    No JSON file found here: C:\HarmonyCore\FullTut2withTestProjects_3\MyApi\Services.Test\TestConstants.Values.json
    Creating a new JSON file
    - Determining parameters for read by primary key...
    Processing file DAT:items.ism
    - Opening DAT:items.ism...
    - Counting records...
    - Determining parameters for read by primary key...
    Processing file DAT:orders.ism
    - Opening DAT:orders.ism...
    - Counting records...
    - Determining parameters for read by primary key...
    Processing file DAT:order_items.ism
    - Opening DAT:order_items.ism...
    - Counting records...
    - Determining parameters for read by primary key...
    Processing file DAT:vendors.ism
    - Opening DAT:vendors.ism...
    - Counting records...
    - Determining parameters for read by primary key...
    
  2. Change to the Services.Test folder:

    cd Services.Test
    
  3. Run unit tests by running the following at the command prompt:

    dotnet test --no-build --logger "console;verbosity=detailed"
    

    You should see output similar to this:

    Passed GetAllCustomers [684 ms]
    Passed GetAllCustomers_Expand_REL_Orders [391 ms]
    Passed GetAllCustomers_Expand_REL_Item [27 ms]
    Passed GetAllCustomers_Expand_All [235 ms]
    Passed GetOneCustomer [24 ms]
    Passed GetOneCustomer_Expand_REL_Orders [19 ms]
    Passed GetOneCustomer_Expand_REL_Item [7 ms]
    Passed GetOneCustomer_Expand_All [11 ms]
    Passed GetCustomer_ByAltKey_State [6 ms]
    Passed GetCustomer_ByAltKey_Zip [3 ms]
    Passed GetCustomer_ByAltKey_PaymentTerms [6 ms]
    Passed UpdateCustomer [236 ms]
    Passed GetAllItems [14 ms]
    Passed GetAllItems_Expand_REL_Vendor [28 ms]
    Passed GetAllItems_Expand_REL_OrderItems [701 ms]
    Passed GetAllItems_Expand_All [759 ms]
    Passed GetOneItem [6 ms]
    Passed GetOneItem_Expand_REL_Vendor [7 ms]
    Passed GetOneItem_Expand_REL_OrderItems [16 ms]
    Passed GetOneItem_Expand_All [13 ms]
    Passed GetItem_ByAltKey_VendorNumber [5 ms]
    Passed GetItem_ByAltKey_Color [5 ms]
    Passed GetItem_ByAltKey_Size [5 ms]
    Passed GetItem_ByAltKey_Name [3 ms]
    Passed UpdateItem [85 ms]
    Passed GetAllOrderItems [957 ms]
    Passed GetAllOrderItems_Expand_REL_Order [1 s]
    Passed GetAllOrderItems_Expand_REL_Item [757 ms]
    Passed GetAllOrderItems_Expand_All [1 s]
    Passed GetOneOrderItem [7 ms]
    Passed GetOneOrderItem_Expand_REL_Order [4 ms]
    Passed GetOneOrderItem_Expand_REL_Item [3 ms]
    Passed GetOneOrderItem_Expand_All [4 ms]
    Passed GetOrderItem_ByAltKey_ItemOrdered [4 ms]
    Passed GetOrderItem_ByAltKey_DateShipped [8 ms]
    Passed GetOrderItem_ByAltKey_InvoiceNumber [4 ms]
    Passed UpdateOrderItem [47 ms]
    Passed GetAllOrders [94 ms]
    Passed GetAllOrders_Expand_REL_OrderItems [2 s]
    Passed GetAllOrders_Expand_REL_Customer [222 ms]
    Passed GetAllOrders_Expand_All [2 s]
    Passed GetOneOrder [4 ms]
    Passed GetOneOrder_Expand_REL_OrderItems [9 ms]
    Passed GetOneOrder_Expand_REL_Customer [3 ms]
    Passed GetOneOrder_Expand_All [3 ms]
    Passed GetOrder_ByAltKey_CustomerNumber [3 ms]
    Passed GetOrder_ByAltKey_DateOrdered [2 ms]
    Passed GetOrder_ByAltKey_DateCompleted [6 ms]
    Passed UpdateOrder [48 ms]
    Passed GetAllVendors [4 ms]
    Passed GetAllVendors_Expand_REL_Items [15 ms]
    Passed GetAllVendors_Expand_All [15 ms]
    Passed GetOneVendor [4 ms]
    Passed GetOneVendor_Expand_REL_Items [9 ms]
    Passed GetOneVendor_Expand_All [3 ms]
    Passed GetVendor_ByAltKey_State [2 ms]
    Passed GetVendor_ByAltKey_Zip [2 ms]
    Passed GetVendor_ByAltKey_PaymentTerms [2 ms]
    Passed UpdateVendor [42 ms]
    
    Test Run Successful.
    Total tests: 59
         Passed: 59
     Total time: 15.2832 Seconds
    

Troubleshooting

If results differ from expected output, use these checks to resolve the most common setup and dependency issues.

  • If many tests fail immediately, run step 25 again to regenerate TestConstants.Values.json.

  • If build errors mention missing OData or caching assemblies, follow steps 13 through 16 to re-check settings.

⚠️ **GitHub.com Fallback** ⚠️