对Blazor RenderFragment元素进行单元测试

时间:2019-01-22 12:00:11

标签: c# xunit blazor

我已经开始编写一种用于动态构建RenderFragment元素的方法。因此,我还试图在方法旁边编写单元测试。

我从一个非常基本的元素开始,但是它失败了。这是测试中的具体方法:

public RenderFragment buildFragment(string element, string elementContent, string[] attribute, string[] attributeContent)
    {
        RenderFragment content = builder => {
            builder.OpenElement(0, element);
            if (attribute != null)
            {
                for (int i = 0; attribute.Length - 1 >= i; ++i)
                {
                    builder.AddAttribute(0, attribute[i], attributeContent[i]);
                }
            }
            if (!string.IsNullOrEmpty(elementContent))
            {
                builder.AddContent(0, elementContent);
            }
            builder.CloseElement();
        };

        return content;
    }

这是我针对使用xUnit的方法进行的第一个基本测试:

public void BuildFragmentReturnsOneElement()
        {
            //Arrange
            RenderFragment fragment = builder =>
            {
                builder.OpenElement(0, "p");
                builder.CloseElement();
            };

            //Act
            RenderFragment result = _dynamicContentHelper.buildFragment("p", string.Empty, null, null);

            //Assert
            Assert.Same(fragment, result);
        }

我收到的错误是:

  

消息:Assert.Same()失败   预期:RenderFragment {方法=无效b__2_0(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder),目标= <> c {}}   实际:RenderFragment {方法=无效b__0(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder),目标= <> c__DisplayClass0_0 {属性= null,attributeContent = null,element =“ p”,elementContent =“”}}}

我不明白为什么片段对象上的 Target 结果上的 Target 不同。

2 个答案:

答案 0 :(得分:1)

RenderFragment是一个Delegate方法,因此当您编写如下代码时:

RenderFragment fragment = builder =>
            {
                builder.OpenElement(0, "p");
                builder.CloseElement();
            };

您不是要创建物化工件,而是声明可以调用的委托。

代码Assert.Same(fragment, result);因此正在比较两个委托,它们显然是不同的-它们指向两种不同的方法。

我相信您应该调查Blazor Source的“测试”文件夹

This section may help a lot

他们应用的技术是检查RenderTree的帧

// Act
var frames = GetRenderTree(component);

// Assert
Assert.Collection(
 frames,
 frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0),
 frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 1),
 frame => AssertFrame.Markup(frame, "\n  <div></div>\n", 2));

Also, this section with a TestRenderer,其中包含此代码

protected RenderTreeFrame[] GetRenderTree(IComponent component)
        {
            var renderer = new TestRenderer();
            renderer.AttachComponent(component);
            component.SetParameters(ParameterCollection.Empty);
            return renderer.LatestBatchReferenceFrames;
        }

看看它们如何进行测试,因为我在这里无法全部复制,但这是关键...

答案 1 :(得分:0)

我发现有一个非常有用的库,用于对Blazor组件进行单元测试,名为bUnit库。测试非常容易编写。这是一个验证按钮单击是否有效的示例。

[Fact]
public void TestCounter()
{
    // Arrange
    var cut = RenderComponent<Counter>();
    cut.Find("p").MarkupMatches("<p>Current count: 0</p>");

    // Act
    var element = cut.Find("button");
    element.Click();

    //Assert
    cut.Find("p").MarkupMatches("<p>Current count: 1</p>");
}

这是另一个示例,其中包括使用JustMock Lite

模拟服务
[Fact]
public void TestFetchData_ForecastIsNull()
{
    // Arrange
    var weatherForecastServiceMock = Mock.Create<IWeatherForecastService>();
    Mock.Arrange(() => weatherForecastServiceMock.GetForecastAsync(Arg.IsAny<DateTime>()))
        .Returns(new TaskCompletionSource<WeatherForecast[]>().Task);
    Services.AddSingleton<IWeatherForecastService>(weatherForecastServiceMock);

    // Act
    var cut = RenderComponent<FetchData>();

    // Assert - that it renders the initial loading message
    var initialExpectedHtml = 
                @"<h1>Weather forecast</h1>
                <p>This component demonstrates fetching data from a service.</p>
                <p><em>Loading...</em></p>";
    cut.MarkupMatches(initialExpectedHtml);
}

示例来自博客文章Unit Testing Blazor Components with bUnit and JustMock