我在我的React项目中使用rxjs
,并且各种组件都已订阅到数据流。有没有一种方法可以测试订阅主题的此类组件:
例如
import { Subject } from 'rxjs';
import { useState, useEffect } from 'react';
import styles from '../index.scss';
function useObservable({ subject, initialValue }) {
const [value, setValue] = useState(initialValue);
useEffect(() => {
const subscription = subject.subscribe({
next: (v) => setValue(v),
});
return () => subscription.unsubscribe();
}, [subject]);
return value;
}
const subject = new Subject();
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function OrderProgress({ orderData }) {
setInterval(() => {
subject.next({
change: getRndInteger(0, 120),
});
}, 10000);
const LIVE_VALUE = useObservable({
subject,
initialValue: { change: 100 },
});
const LIVE_STATUS = LIVE_VALUE.change;
return (
<div className={styles.progressCard}>
<div
className={styles.progressBar}
style={{ width: `${((100 / (orderData.price)) * LIVE_STATUS)}%`, maxWidth: '99%' }}
/>
<div className={styles.liveData}>
<span className={styles.label}>LIVE</span>
{/* TODO: data from socket */}
<span className={styles.value}>{LIVE_STATUS}</span>
</div>
<div className={styles.progressDetail}>
{orderData.exchange}
: Awaiting Execution…
</div>
<div className={styles.targetData}>
<span className={styles.label}>Target</span>
<span className={styles.value}>{orderData.price}</span>
</div>
</div>
);
}
我怎样才能最好地使用笑话和酶正确地测试上述成分。
答案 0 :(得分:2)
这是单元测试解决方案:
index.tsx
:
import { Subject } from "rxjs";
import React, { useState, useEffect } from "react";
// import styles from "../index.scss";
const styles = {
progressCard: "progressCard",
progressBar: "progressBar",
liveData: "liveData",
label: "label",
value: "value",
progressDetail: "progressDetail",
targetData: "targetData"
};
function useObservable({ subject, initialValue }) {
const [value, setValue] = useState(initialValue);
useEffect(() => {
const subscription = subject.subscribe({
next: v => setValue(v)
});
return () => subscription.unsubscribe();
}, [subject]);
return value;
}
const subject = new Subject();
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function OrderProgress({ orderData }) {
setInterval(() => {
subject.next({
change: exports.getRndInteger(0, 120)
});
}, 10000);
const LIVE_VALUE = useObservable({
subject,
initialValue: { change: 100 }
});
const LIVE_STATUS = LIVE_VALUE.change;
return (
<div className={styles.progressCard}>
<div
className={styles.progressBar}
style={{
width: `${(100 / orderData.price) * LIVE_STATUS}%`,
maxWidth: "99%"
}}
/>
<div className={styles.liveData}>
<span className={styles.label}>LIVE</span>
{/* TODO: data from socket */}
<span className={styles.value}>{LIVE_STATUS}</span>
</div>
<div className={styles.progressDetail}>
{orderData.exchange}: Awaiting Execution…
</div>
<div className={styles.targetData}>
<span className={styles.label}>Target</span>
<span className={styles.value}>{orderData.price}</span>
</div>
</div>
);
}
exports.getRndInteger = getRndInteger;
exports.OrderProgress = OrderProgress;
exports.useObservable = useObservable;
exports.subject = subject;
index.spec.tsx
:
const { OrderProgress } = require("./");
const mod = require("./");
import React from "react";
import { mount } from "enzyme";
import { act } from "react-dom/test-utils";
jest.useFakeTimers();
afterEach(() => {
jest.restoreAllMocks();
});
describe("OrderProgress", () => {
it("should passs", () => {
const getRndIntegerSpy = jest
.spyOn(mod, "getRndInteger")
.mockReturnValueOnce(200);
const subscribeSpy = jest.spyOn(mod.subject, "subscribe");
const mProps = { orderData: { price: 1000 } };
const wrapper = mount(<OrderProgress {...mProps}></OrderProgress>);
expect(wrapper.find(".progressBar").prop("style")).toEqual({
width: "10%",
maxWidth: "99%"
});
expect(wrapper).toMatchSnapshot();
act(() => {
jest.advanceTimersByTime(10 * 1000);
});
wrapper.update();
expect(wrapper.find(".progressBar").prop("style")).toEqual({
width: "20%",
maxWidth: "99%"
});
expect(subscribeSpy).toBeCalledTimes(1);
expect(getRndIntegerSpy).toBeCalledWith(0, 120);
expect(wrapper).toMatchSnapshot();
});
});
describe("getRndInteger", () => {
it("should pass", () => {
const randomSpy = jest.spyOn(Math, "random").mockReturnValueOnce(1);
const actual = mod.getRndInteger(1, 100);
expect(actual).toBe(101);
expect(randomSpy).toBeCalledTimes(1);
});
});
带有覆盖率报告的单元测试结果:
PASS src/stackoverflow/59028966/index.spec.tsx (8.918s)
OrderProgress
✓ should passs (64ms)
getRndInteger
✓ should pass (1ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 96.15 | 100 | 85.71 | 100 | |
index.tsx | 96.15 | 100 | 85.71 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 10.504s
index.spec.tsx.snap
:
// Jest Snapshot v1
exports[`OrderProgress should passs 1`] = `
<OrderProgress
orderData={
Object {
"price": 1000,
}
}
>
<div
className="progressCard"
>
<div
className="progressBar"
style={
Object {
"maxWidth": "99%",
"width": "10%",
}
}
/>
<div
className="liveData"
>
<span
className="label"
>
LIVE
</span>
<span
className="value"
>
100
</span>
</div>
<div
className="progressDetail"
>
: Awaiting Execution…
</div>
<div
className="targetData"
>
<span
className="label"
>
Target
</span>
<span
className="value"
>
1000
</span>
</div>
</div>
</OrderProgress>
`;
exports[`OrderProgress should passs 2`] = `
<OrderProgress
orderData={
Object {
"price": 1000,
}
}
>
<div
className="progressCard"
>
<div
className="progressBar"
style={
Object {
"maxWidth": "99%",
"width": "20%",
}
}
/>
<div
className="liveData"
>
<span
className="label"
>
LIVE
</span>
<span
className="value"
>
200
</span>
</div>
<div
className="progressDetail"
>
: Awaiting Execution…
</div>
<div
className="targetData"
>
<span
className="label"
>
Target
</span>
<span
className="value"
>
1000
</span>
</div>
</div>
</OrderProgress>
`;
源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59028966