Assert the Value of a WF Service Variable During a Unit Test

半腔热情 提交于 2020-01-04 04:43:27

问题


I need to assert the value of a variable in a workflow service.

I've already downloaded and am using the Microsoft.Activities.UnitTesting framework from CodePlex to test the workflow service endpoint, return values, and flow logic - but I need to verify the value of a variable after calling into an endpoint and getting a response - is that possible?

If it's not is there some other type of workaround that might work that doesn't involve changing the workflow itself to produce an output parameter? Because when in production I certainly wouldn't need one.

Thanks!

UPDATE 2.A

Currently using the stubs method instead of the WCF method for testing the service.

[TestMethod]
[DeploymentItem(@"TestService\Service1.xamlx")]
public void TestValueOfInteger1AfterStart()
{
    // inject the mocks into the service
    var xamlInjector = new XamlInjector("Service1.xamlx");
    xamlInjector.ReplaceAll(typeof(Receive), typeof(ReceiveStub));
    xamlInjector.ReplaceAll(typeof(SendReply), typeof(SendReplyStub));

    // setup the messages
    var stubExtension = new MessagingStubExtension();

    // enqueue a message for the receive activity using parameters content
    stubExtension.EnqueueReceive(XName.Get("{http://tempuri.org/}IService"), "Start", null);

    // setup the host
    var host = WorkflowInvokerTest.Create(xamlInjector.GetWorkflowService().Body);
    host.Extensions.Add(stubExtension);

    try
    {
        host.TestActivity();
        ...

UPDATE 2.B

So, after some more effort I found that instead of using the WCF endpoint for unit test I could recover a context through reflection if I used the stubs. Above is an exerpt of the stubs unit testing code and below is the reflection code I'm using to get a refreshed ActivityContext. However, now I'm getting the following error when trying to get the value of the variable.

The interesting part is that you can clearly see the activity the context is tied to is the activity in which it is defined - the poor framework is just a little confused.

...
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;

// recover the WorkflowInstance
var proxy = stubExtension.GetType().GetProperty("InstanceProxy",
                                                bindingFlags).GetValue(stubExtension,
                                                                       bindingFlags,
                                                                       null,
                                                                       null,
                                                                       null) as WorkflowInstanceProxy;

// recover the WorkflowInstance
var fieldInfo = proxy.GetType().GetField("instance", bindingFlags);
var workflowInstance = fieldInfo.GetValue(proxy) as WorkflowApplication;

// recover the ActivityExecutor
fieldInfo = workflowInstance.GetType().BaseType.GetField("executor", bindingFlags);
dynamic activityExecutor = fieldInfo.GetValue(workflowInstance);

// recover the rootInstance
fieldInfo = activityExecutor.GetType().GetField("rootInstance", bindingFlags);
var rootInstance = fieldInfo.GetValue(activityExecutor) as ActivityInstance;

// recover the cachedResolutionContext
fieldInfo = activityExecutor.GetType().GetField("cachedResolutionContext", bindingFlags);
var cachedResolutionContext = fieldInfo.GetValue(activityExecutor) as ActivityContext;

MethodInfo methodInfo = cachedResolutionContext.GetType().GetMethod("Reinitialize", bindingFlags);
methodInfo.Invoke(cachedResolutionContext, bindingFlags, null, new object[]
                                                                   {
                                                                       rootInstance,
                                                                       activityExecutor
                                                                   }, null);

var val = (int)((Sequence)rootInstance.Activity).Variables.First(x => x.Name == "integer1").Get(cachedResolutionContext);
Assert.AreEqual(val, 1, "The integer value of integer1 is not correct.");

回答1:


You could use AppFabric tracking and monitor the variable.

However, the question raises the further question that if you are already testing flow logic and outputs, why do you need to test the internal state of the wf instance?




回答2:


I started using this tool to do my asserts of objects:

http://comparenetobjects.codeplex.com/

It is open source and does a good job of using reflection to assert the values of complex objects.



来源:https://stackoverflow.com/questions/9672878/assert-the-value-of-a-wf-service-variable-during-a-unit-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!