Explore all Unit Testing open source software, libraries, packages, source code, cloud functions and APIs.

Popular New Releases in Unit Testing

googletest

v1.11.0

mocha

v9.2.2

ava

v4.1.0

learn-go-with-tests

Fixed typo in revisiting arrays and slices

jasmine

4.1.0

Popular Libraries in Unit Testing

googletest

by google doticonc++doticon

star image 23619 doticonBSD-3-Clause

GoogleTest - Google Testing and Mocking Framework

mocha

by mochajs doticonjavascriptdoticon

star image 21297 doticonMIT

โ˜•๏ธ simple, flexible, fun javascript test framework for node.js & the browser

enzyme

by enzymejs doticonjavascriptdoticon

star image 19677 doticonMIT

JavaScript Testing utilities for React

ava

by avajs doticonjavascriptdoticon

star image 19628 doticonMIT

Node.js test runner that lets you develop with confidence ๐Ÿš€

phpunit

by sebastianbergmann doticonphpdoticon

star image 18324 doticonNOASSERTION

The PHP Unit Testing framework.

learn-go-with-tests

by quii doticongodoticon

star image 17304 doticonMIT

Learn Go with test-driven development

jasmine

by jasmine doticonjavascriptdoticon

star image 15320 doticon

Simple JavaScript testing framework for browsers and node.js

Catch2

by catchorg doticonc++doticon

star image 14767 doticonBSL-1.0

A modern, C++-native, test framework for unit-tests, TDD and BDD - using C++14, C++17 and later (C++11 support is in v2.x branch, and C++03 on the Catch1.x branch)

testify

by stretchr doticongodoticon

star image 14231 doticonMIT

A toolkit with common assertions and mocks that plays nicely with the standard library

Trending New libraries in Unit Testing

smuggler

by defparam doticonpythondoticon

star image 912 doticonMIT

Smuggler - An HTTP Request Smuggling / Desync testing tool written in Python 3

pynguin

by se2p doticonpythondoticon

star image 865 doticonNOASSERTION

The PYthoN General UnIt Test geNerator is a test-generation tool for Python

playwright-test

by microsoft doticontypescriptdoticon

star image 780 doticonNOASSERTION

Build a cross-browser end-to-end test suite with Playwright.

jest-clean-console-reporter

by jevakallio doticonjavascriptdoticon

star image 524 doticonMIT

A Jest Reporter to group, hide and prettify spammy console warnings

goc

by qiniu doticongodoticon

star image 505 doticonApache-2.0

A Comprehensive Coverage Testing System for The Go Programming Language

testza

by MarvinJWendt doticongodoticon

star image 385 doticonMIT

Full-featured test framework for Go! Assertions, fuzzing, input testing, output capturing, and much more! ๐Ÿ•

baretest

by volument doticonjavascriptdoticon

star image 370 doticonMIT

An extremely fast and simple JavaScript test runner.

DocTest

by SwiftDocOrg doticonswiftdoticon

star image 363 doticon

An experimental tool for testing Swift example code in documentation.

TestParameterInjector

by google doticonjavadoticon

star image 259 doticonApache-2.0

A simple yet powerful parameterized test runner for Java.

Top Authors in Unit Testing

1

sebastianbergmann

19 Libraries

star icon24123

2

kentcdodds

11 Libraries

star icon1657

3

microsoft

10 Libraries

star icon2759

4

google

10 Libraries

star icon25001

5

PacktPublishing

9 Libraries

star icon190

6

Codeception

8 Libraries

star icon5806

7

eddyerburgh

7 Libraries

star icon311

8

test-unit

7 Libraries

star icon277

9

bahmutov

6 Libraries

star icon21

10

dwyl

6 Libraries

star icon2241

1

19 Libraries

star icon24123

2

11 Libraries

star icon1657

3

10 Libraries

star icon2759

4

10 Libraries

star icon25001

5

9 Libraries

star icon190

6

8 Libraries

star icon5806

7

7 Libraries

star icon311

8

7 Libraries

star icon277

9

6 Libraries

star icon21

10

6 Libraries

star icon2241

Trending Kits in Unit Testing

Code coverage is a measure of how much source code was tested. It's often used to guide testing activities and can be used to enhance quality. Good code coverage does not guarantee your software is bug-free, but it does determine that your code has been executed during a test run. The most powerful feature of this unit testing framework is that it can be used to test any kind of software, ranging from libraries to web applications. There are lots of unit testing frameworks for .NET developers, but the most popular and reliable ones are xunit - open source, communityfocused unit testing tool; fluentassertions - Fluent API for asserting the results of unit tests; AutoFixture is designed to make Test-Driven Development more productive and unit tests more refactoring-safe.

Unit testing is a software testing method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application like functions, classes, procedures, interfaces, etc. In procedural programming, a unit may be an individual program, function, procedure, or even a single line of code. In object-oriented programming (OOP), the smallest unit is a method, which may belong to a base/ super class or abstract class, or derived/ child class. Here are 12 best Java Unit Testing Open Source libraries in 2022 including mockito - popular Mocking framework for unit tests written; powermock - Java framework for unit testing; ArchUnit - a free, simple and extensible library for checking the architecture of your Java code.

Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation. Unit testing can be done manually but is often automated. The goal of unit testing is to isolate each part of the program and show that individual parts are correct in terms of requirements and functionality. A unit test provides a strict, written contract that the piece of code must satisfy. The entire list of the best 17 best Python Unit Testing Open Source libraries including phpunit - The PHP Unit Testing framework; mockery - simple yet flexible PHP mock object framework; atoum - The modern, simple and intuitive PHP unit testing framework.

Unit testing is the first level of software testing where individual units/ components of a software are tested. The purpose is to validate that each unit of the software performs as designed. A unit is the smallest testable part of any software. It usually has one or a few inputs and usually a single output. Python Unit testing frameworks provide a solid base on which to build your test suite for any python codebase. Python Unit testing frameworks also help in automated testing, sharing test cases across multiple interfaces and monitoring code quality. Following are the best 14 best Python Unit Testing Open Source libraries including pynguin - PYthoN General UnIt Test geNerator is a testgeneration tool; unittest-xml-reporting - unit tes based test runner with Ant/JUnit like XML reporting; codepipeline-nested-cfn - CloudFormation templates, CodeBuild build specification & Python scripts to perform unit tests of a nested CloudFormation template.

Unit testing helps developers by allowing them to refactor their code more confidently, catch regressions early on, and prevent bugs from reaching production. This can have significant benefits for software development teams. JavaScript is easy to get started with, it can quickly become a complex language with many quirks and gotchas. The good news is that there are many tools and frameworks that help us handle those complexities. One such tool is unit testing. Weโ€™ve analyzed the most popular open-source JavaScript unit testing frameworks in terms of their features, functionality, and community support. We recommend the following 13 best JavaScript Unit Testing libraries including qunit - An easytouse JavaScript unit testing framework; chutzpah - open-source JavaScript test runner; qunit - An easytouse JavaScript Unit Testing framework.

Unit test is a code which ensures that the program logic works as expected by verifying each component of it. The main goal is to isolate each part of the program and show that the individual parts are correct. The most powerful feature of this unit testing framework is that it can be used to test any kind of software, ranging from libraries to web applications. When it comes to Unit Testing in Ruby, there are many open source libraries that you can use. Here we'll focus on the 7 best Unit Testing libraries for Ruby including Riot - a fast, expressive, and contextual ruby unit testing framework; single_test - Rake tasks to invoke single tests/specs with rakish syntax; riot-rails - Riot macros and helpers for Rails application testing

Unit testing is the first level of software testing where individual units/ components of a software are tested. The purpose is to validate that each unit of the software performs as designed. A unit is the smallest testable part of any software. It usually has one or a few inputs and usually a single output. Good code coverage does not guarantee your software is bug-free, but it does determine that your code has been executed during a test run. In this list, we list down 11 best C++ Unit Testing Open Source libraries that you can use in your project. Such as Catch2 - A modern, Cnative, headeronly, test framework for unittests, TDD and BDD using C11, C14, C17 and later; cpputest - CppUTest unit testing and mocking framework for C/C++; unittest-cpp | A lightweight unit testing framework for C++.

Trending Discussions on Unit Testing

assert that all fields in 2 objects are the same c#

Skipping a method execution using Mockito

How to locally unit-test Chainlink's Verifiable Random Function?

How do I give my JSON schema an absolute URL for its $id when I haven't published it yet because it hasn't been tested yet?

How to mock function without class in Kotlin?

What is the 'X' in this insert > X'3C2F756C3E'

Deploying Uniswap v2 / Sushiswap or similar in Brownie, Hardhat or Truffle test suite

How to add unit testing in strapi version 4 using jest?

What exactly is/means "System.IO.Stream+NullStream"?

Unit testing SwiftUI/Combine @Published boolean values

QUESTION

assert that all fields in 2 objects are the same c#

Asked 2022-Apr-08 at 08:50

I am doing unit testing, and basically want to check that the data that 2 objects hold is the same

1Assert.AreEqual(object1, object2);   
2Assert.IsTrue(object1.Equals(object2)); //this of course doesn't work
3

I am searching for the C# equivalent of assertJ

1Assert.AreEqual(object1, object2);   
2Assert.IsTrue(object1.Equals(object2)); //this of course doesn't work
3Assert.That(object1).isEqualToComparingFieldByField(object2)
4

ANSWER

Answered 2022-Apr-08 at 07:47

You could either use records (c# 9 +) or you have to override the Equals method (if you have access and you can change the objects that you're working with). Records example:

1Assert.AreEqual(object1, object2);   
2Assert.IsTrue(object1.Equals(object2)); //this of course doesn't work
3Assert.That(object1).isEqualToComparingFieldByField(object2)
4var point = new Point(3, 4);
5var point2 = new Point(3, 4);
6
7var test = point.Equals(point2); //this is true
8
9public record Point(int X, int Y);
10

with classes:

1Assert.AreEqual(object1, object2);   
2Assert.IsTrue(object1.Equals(object2)); //this of course doesn't work
3Assert.That(object1).isEqualToComparingFieldByField(object2)
4var point = new Point(3, 4);
5var point2 = new Point(3, 4);
6
7var test = point.Equals(point2); //this is true
8
9public record Point(int X, int Y);
10public class Point
11{
12    public int X { get; }
13    public int Y { get; }
14
15
16    public override bool Equals(object? obj)
17    {
18        if (obj == null)
19         return false;
20
21        return obj is Point point && (point.X == X && point.Y == Y);
22    }
23
24    public override int GetHashCode()
25    {
26        return HashCode.Combine(X, Y);
27    }
28}
29

if you are not allowed to touch the implementation, then you could use serialization and compare the strings:

1Assert.AreEqual(object1, object2);   
2Assert.IsTrue(object1.Equals(object2)); //this of course doesn't work
3Assert.That(object1).isEqualToComparingFieldByField(object2)
4var point = new Point(3, 4);
5var point2 = new Point(3, 4);
6
7var test = point.Equals(point2); //this is true
8
9public record Point(int X, int Y);
10public class Point
11{
12    public int X { get; }
13    public int Y { get; }
14
15
16    public override bool Equals(object? obj)
17    {
18        if (obj == null)
19         return false;
20
21        return obj is Point point && (point.X == X && point.Y == Y);
22    }
23
24    public override int GetHashCode()
25    {
26        return HashCode.Combine(X, Y);
27    }
28}
29var obj1Str = JsonConvert.SerializeObject(object1);
30var obj2Str = JsonConvert.SerializeObject(object2);
31Assert.Equal(obj1Str, obj2Str);
32

using Newtonsoft.Json nuget

Source https://stackoverflow.com/questions/71793327

QUESTION

Skipping a method execution using Mockito

Asked 2022-Mar-21 at 09:41

Iโ€™m using Mockito for unit testing and I want to skip the execution of a method.

I referred to this ticket Skip execution of a line using Mockito. Here, I assume doSomeTask() and createLink() methods are in different classes. But in my case, both the methods are in the same class (ActualClass.java).

1//Actual Class
2
3public class ActualClass{
4    
5    //The method being tested
6    public void method(){
7        //some business logic
8        validate(param1, param2);
9
10        //some business logic
11    }
12
13    public void validate(arg1, arg2){
14        //do something
15    }
16}
17
18//Test class
19
20public class ActualClassTest{
21
22    @InjectMocks
23    private ActualClass actualClassMock;
24
25    @Test
26    public void test_method(){
27
28        ActualClass actualClass = new ActualClass();
29        ActualClass spyActualClass = Mockito.spy(actualClass);
30
31        // validate method creates a null pointer exception, due to some real time data fetch from elastic
32
33        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
34        actualClassMock.method();
35    }
36}
37

Since there arises a null pointer exception when the validate method is executed, Iโ€™m trying to skip the method call by spying the ActualClass object as stated in the ticket I mentioned above. Still, the issue is not resolve. The validate method gets executed and creates a null pointer exception due to which the actual test method cannot be covered.

So, how do I skip the execution of the validate() method that is within the same class.

ANSWER

Answered 2022-Mar-04 at 09:36

You must always use your spy class when calling method().

1//Actual Class
2
3public class ActualClass{
4    
5    //The method being tested
6    public void method(){
7        //some business logic
8        validate(param1, param2);
9
10        //some business logic
11    }
12
13    public void validate(arg1, arg2){
14        //do something
15    }
16}
17
18//Test class
19
20public class ActualClassTest{
21
22    @InjectMocks
23    private ActualClass actualClassMock;
24
25    @Test
26    public void test_method(){
27
28        ActualClass actualClass = new ActualClass();
29        ActualClass spyActualClass = Mockito.spy(actualClass);
30
31        // validate method creates a null pointer exception, due to some real time data fetch from elastic
32
33        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
34        actualClassMock.method();
35    }
36}
37   @Test
38    public void test_method(){
39        ActualClass spyActualClass = Mockito.spy(actualClassMock);
40
41        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
42        spyActualClass.method();
43    }
44

In practice, instead of

1//Actual Class
2
3public class ActualClass{
4    
5    //The method being tested
6    public void method(){
7        //some business logic
8        validate(param1, param2);
9
10        //some business logic
11    }
12
13    public void validate(arg1, arg2){
14        //do something
15    }
16}
17
18//Test class
19
20public class ActualClassTest{
21
22    @InjectMocks
23    private ActualClass actualClassMock;
24
25    @Test
26    public void test_method(){
27
28        ActualClass actualClass = new ActualClass();
29        ActualClass spyActualClass = Mockito.spy(actualClass);
30
31        // validate method creates a null pointer exception, due to some real time data fetch from elastic
32
33        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
34        actualClassMock.method();
35    }
36}
37   @Test
38    public void test_method(){
39        ActualClass spyActualClass = Mockito.spy(actualClassMock);
40
41        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
42        spyActualClass.method();
43    }
44actualClassMock.method();
45

you must use

1//Actual Class
2
3public class ActualClass{
4    
5    //The method being tested
6    public void method(){
7        //some business logic
8        validate(param1, param2);
9
10        //some business logic
11    }
12
13    public void validate(arg1, arg2){
14        //do something
15    }
16}
17
18//Test class
19
20public class ActualClassTest{
21
22    @InjectMocks
23    private ActualClass actualClassMock;
24
25    @Test
26    public void test_method(){
27
28        ActualClass actualClass = new ActualClass();
29        ActualClass spyActualClass = Mockito.spy(actualClass);
30
31        // validate method creates a null pointer exception, due to some real time data fetch from elastic
32
33        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
34        actualClassMock.method();
35    }
36}
37   @Test
38    public void test_method(){
39        ActualClass spyActualClass = Mockito.spy(actualClassMock);
40
41        doNothing().when(spyActualClass).validate(Mockito.any(), Mockito.any());
42        spyActualClass.method();
43    }
44actualClassMock.method();
45spyActualClass.method();
46

Source https://stackoverflow.com/questions/71349090

QUESTION

How to locally unit-test Chainlink's Verifiable Random Function?

Asked 2022-Mar-08 at 04:12
Context

While trying to set up a basic self-hosted unit testing environment (and CI) that tests this Chainlink VRF random number contract, I am experiencing slight difficulties in how to simulate any relevant blockchains/testnets locally.

For example, I found this repository that tests Chainlinks VRF. However, for default deployment it suggests/requires a free KOVAN_RPC_URL e.g. from Infura's site and even for "local deployment" it suggests/requires a free MAINNET_RPC_URL from e.g. Alchemy's site.

Attempt/baseline

I adopted a unit test environment from the waffle framework which is described as:

Filestructure
1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10
Filecontents

AmIRichAlready.sol

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34

The RandomNumberConsumer.sol filecontent is already on stackexange over here.

AmIRichAlready.test.ts

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78

mocha.opts

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82

package.json

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83  "name": "example-dynamic-mocking-and-testing-calls",
84  "version": "1.0.0",
85  "main": "index.js",
86  "license": "MIT",
87  "scripts": {
88    "test": "export NODE_ENV=test && mocha",
89    "build": "waffle",
90    "lint": "eslint '{src,test}/**/*.ts'",
91    "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92  },
93  "devDependencies": {
94    "@openzeppelin/contracts": "^4.3.1",
95    "@types/chai": "^4.2.3",
96    "@types/mocha": "^5.2.7",
97    "@typescript-eslint/eslint-plugin": "^2.30.0",
98    "@typescript-eslint/parser": "^2.30.0",
99    "chai": "^4.3.4",
100    "eslint": "^6.8.0",
101    "eslint-plugin-import": "^2.20.2",
102    "ethereum-waffle": "^3.4.0",
103    "ethers": "^5.0.17",
104    "mocha": "^7.2.0",
105    "ts-node": "^8.9.1",
106    "typescript": "^3.8.3"
107  }
108}
109

tsconfig.json

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83  "name": "example-dynamic-mocking-and-testing-calls",
84  "version": "1.0.0",
85  "main": "index.js",
86  "license": "MIT",
87  "scripts": {
88    "test": "export NODE_ENV=test && mocha",
89    "build": "waffle",
90    "lint": "eslint '{src,test}/**/*.ts'",
91    "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92  },
93  "devDependencies": {
94    "@openzeppelin/contracts": "^4.3.1",
95    "@types/chai": "^4.2.3",
96    "@types/mocha": "^5.2.7",
97    "@typescript-eslint/eslint-plugin": "^2.30.0",
98    "@typescript-eslint/parser": "^2.30.0",
99    "chai": "^4.3.4",
100    "eslint": "^6.8.0",
101    "eslint-plugin-import": "^2.20.2",
102    "ethereum-waffle": "^3.4.0",
103    "ethers": "^5.0.17",
104    "mocha": "^7.2.0",
105    "ts-node": "^8.9.1",
106    "typescript": "^3.8.3"
107  }
108}
109{
110  "compilerOptions": {
111    "declaration": true,
112    "esModuleInterop": true,
113    "lib": [
114      "ES2018"
115    ],
116    "module": "CommonJS",
117    "moduleResolution": "node",
118    "outDir": "dist",
119    "resolveJsonModule": true,
120    "skipLibCheck": true,
121    "strict": true,
122    "target": "ES2018"
123  }
124
125  // custom test in vrfContract
126  it('Tests if a random number is returned', async () => {
127    expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128  });
129}
130

waffle.json

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83  "name": "example-dynamic-mocking-and-testing-calls",
84  "version": "1.0.0",
85  "main": "index.js",
86  "license": "MIT",
87  "scripts": {
88    "test": "export NODE_ENV=test && mocha",
89    "build": "waffle",
90    "lint": "eslint '{src,test}/**/*.ts'",
91    "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92  },
93  "devDependencies": {
94    "@openzeppelin/contracts": "^4.3.1",
95    "@types/chai": "^4.2.3",
96    "@types/mocha": "^5.2.7",
97    "@typescript-eslint/eslint-plugin": "^2.30.0",
98    "@typescript-eslint/parser": "^2.30.0",
99    "chai": "^4.3.4",
100    "eslint": "^6.8.0",
101    "eslint-plugin-import": "^2.20.2",
102    "ethereum-waffle": "^3.4.0",
103    "ethers": "^5.0.17",
104    "mocha": "^7.2.0",
105    "ts-node": "^8.9.1",
106    "typescript": "^3.8.3"
107  }
108}
109{
110  "compilerOptions": {
111    "declaration": true,
112    "esModuleInterop": true,
113    "lib": [
114      "ES2018"
115    ],
116    "module": "CommonJS",
117    "moduleResolution": "node",
118    "outDir": "dist",
119    "resolveJsonModule": true,
120    "skipLibCheck": true,
121    "strict": true,
122    "target": "ES2018"
123  }
124
125  // custom test in vrfContract
126  it('Tests if a random number is returned', async () => {
127    expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128  });
129}
130{
131  "compilerType": "solcjs",
132  "compilerVersion": "0.6.2",
133  "sourceDirectory": "./src",
134  "outputDirectory": "./build"
135}
136

The yarn.lock file content is a bit large, and it's auto-generated, so you can find it on the Waffle framework repository. Similarly, the package.json can be found here, in the same repository.

Commands

One can also simply clone the repo with the specified filestructure here, and run the tests with the following commands:

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83  "name": "example-dynamic-mocking-and-testing-calls",
84  "version": "1.0.0",
85  "main": "index.js",
86  "license": "MIT",
87  "scripts": {
88    "test": "export NODE_ENV=test && mocha",
89    "build": "waffle",
90    "lint": "eslint '{src,test}/**/*.ts'",
91    "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92  },
93  "devDependencies": {
94    "@openzeppelin/contracts": "^4.3.1",
95    "@types/chai": "^4.2.3",
96    "@types/mocha": "^5.2.7",
97    "@typescript-eslint/eslint-plugin": "^2.30.0",
98    "@typescript-eslint/parser": "^2.30.0",
99    "chai": "^4.3.4",
100    "eslint": "^6.8.0",
101    "eslint-plugin-import": "^2.20.2",
102    "ethereum-waffle": "^3.4.0",
103    "ethers": "^5.0.17",
104    "mocha": "^7.2.0",
105    "ts-node": "^8.9.1",
106    "typescript": "^3.8.3"
107  }
108}
109{
110  "compilerOptions": {
111    "declaration": true,
112    "esModuleInterop": true,
113    "lib": [
114      "ES2018"
115    ],
116    "module": "CommonJS",
117    "moduleResolution": "node",
118    "outDir": "dist",
119    "resolveJsonModule": true,
120    "skipLibCheck": true,
121    "strict": true,
122    "target": "ES2018"
123  }
124
125  // custom test in vrfContract
126  it('Tests if a random number is returned', async () => {
127    expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128  });
129}
130{
131  "compilerType": "solcjs",
132  "compilerVersion": "0.6.2",
133  "sourceDirectory": "./src",
134  "outputDirectory": "./build"
135}
136git clone git@github.com:a-t-2/chainlink.git
137git clone git@github.com:a-t-2/test_vrf3.git
138cd test_vrf3
139sudo apt install npm
140npm install
141npm audit fix
142npm install --save-dev ethereum-waffle
143npm install @openzeppelin/contracts -D
144npm i chai -D
145npm i mocha -D
146rm -r build
147npx waffle
148npx mocha
149npm test
150
Test Output

This will test the AmIRichAlready.sol file and output:

1src____AmIRichAlready.sol
2   |____RandomNumberConsumer.sol
3   |
4test____AmIRichAlready.test.ts
5   |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13    function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17    IERC20 private tokenContract;
18    uint public richness = 1000000 * 10 ** 18;
19
20    constructor (IERC20 _tokenContract) public {
21        tokenContract = _tokenContract;
22    }
23
24    function check() public view returns (bool) {
25        uint balance = tokenContract.balanceOf(msg.sender);
26        return balance > richness;
27    }
28
29    // IS THIS NEEDED???
30    function setRichness(uint256 _richness) public {
31      richness = _richness;
32    }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44  let mockERC20: Contract;
45  let contract: Contract;
46  let vrfContract: Contract;
47  let wallet: Wallet;
48
49  beforeEach(async () => {
50    [wallet] = new MockProvider().getWallets();
51    mockERC20 = await deployMockContract(wallet, IERC20.abi);
52    contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53    vrfContract = await deployContract(wallet, RandomNumberConsumer);
54  });
55
56  it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57    await mockERC20.mock.balanceOf
58      .withArgs(wallet.address)
59      .returns(utils.parseEther('999999'));
60    await contract.check();
61    expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62  });
63
64  it('returns false if the wallet has less than 1000000 coins', async () => {
65    await mockERC20.mock.balanceOf
66      .withArgs(wallet.address)
67      .returns(utils.parseEther('999999'));
68    expect(await contract.check()).to.be.equal(false);
69  });
70
71  it('returns true if the wallet has at least 1000000 coins', async () => {
72    await mockERC20.mock.balanceOf
73      .withArgs(wallet.address)
74      .returns(utils.parseEther('1000000'));
75    expect(await contract.check()).to.be.equal(false);
76  });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83  "name": "example-dynamic-mocking-and-testing-calls",
84  "version": "1.0.0",
85  "main": "index.js",
86  "license": "MIT",
87  "scripts": {
88    "test": "export NODE_ENV=test && mocha",
89    "build": "waffle",
90    "lint": "eslint '{src,test}/**/*.ts'",
91    "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92  },
93  "devDependencies": {
94    "@openzeppelin/contracts": "^4.3.1",
95    "@types/chai": "^4.2.3",
96    "@types/mocha": "^5.2.7",
97    "@typescript-eslint/eslint-plugin": "^2.30.0",
98    "@typescript-eslint/parser": "^2.30.0",
99    "chai": "^4.3.4",
100    "eslint": "^6.8.0",
101    "eslint-plugin-import": "^2.20.2",
102    "ethereum-waffle": "^3.4.0",
103    "ethers": "^5.0.17",
104    "mocha": "^7.2.0",
105    "ts-node": "^8.9.1",
106    "typescript": "^3.8.3"
107  }
108}
109{
110  "compilerOptions": {
111    "declaration": true,
112    "esModuleInterop": true,
113    "lib": [
114      "ES2018"
115    ],
116    "module": "CommonJS",
117    "moduleResolution": "node",
118    "outDir": "dist",
119    "resolveJsonModule": true,
120    "skipLibCheck": true,
121    "strict": true,
122    "target": "ES2018"
123  }
124
125  // custom test in vrfContract
126  it('Tests if a random number is returned', async () => {
127    expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128  });
129}
130{
131  "compilerType": "solcjs",
132  "compilerVersion": "0.6.2",
133  "sourceDirectory": "./src",
134  "outputDirectory": "./build"
135}
136git clone git@github.com:a-t-2/chainlink.git
137git clone git@github.com:a-t-2/test_vrf3.git
138cd test_vrf3
139sudo apt install npm
140npm install
141npm audit fix
142npm install --save-dev ethereum-waffle
143npm install @openzeppelin/contracts -D
144npm i chai -D
145npm i mocha -D
146rm -r build
147npx waffle
148npx mocha
149npm test
150  Am I Rich Already
151    โœ“ checks if contract called balanceOf with certain wallet on the ERC20 token (249ms)
152    โœ“ returns false if the wallet has less than 1000000 coins (190ms)
153    โœ“ returns true if the wallet has at least 1000000 coins (159ms)
154    Tests if a random number is returned:
155     Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"RuntimeError","results":{"0x0a0b028de6cf6e8446853a300061305501136cefa5f5eb3e96afd95dbd73dd92":{"error":"revert","program_counter":609,"return":"0x"}},"hashes":["0x0a0b028de6cf6e8446853a300061305501136cefa5f5eb3e96afd95dbd73dd92"],"message":"VM Exception while processing transaction: revert"}, tx={"data":"0xdbdff2c1","to":{},"from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff","gasPrice":{"type":"BigNumber","hex":"0x77359400"},"type":0,"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.4.1)
156      at Logger.makeError (node_modules/@ethersproject/logger/src.ts/index.ts:225:28)
157      at Logger.throwError (node_modules/@ethersproject/logger/src.ts/index.ts:237:20)
158      at /home/name/git/trucol/tested/new_test/test_vrf3/node_modules/@ethersproject/abstract-signer/src.ts/index.ts:301:31
159      at process._tickCallback (internal/process/next_tick.js:68:7)
160
161
162
163  3 passing (4s)
164
Question

Which set of files, file structure and commands do I need to automatically test whether the getRandomNumber() contract returns an integer if sufficient "gas" is provided, and an error otherwise?

ANSWER

Answered 2021-Sep-09 at 04:35

to test locally you need to make use of mocks which can simulate having an oracle network. Because you're working locally, a Chainlink node doesn't know about your local blockchain, so you can't actually do proper VRF requests. Note you can try deploy a local Chainlink node and a local blockchain and have them talk, but it isn't fully supported yet so you may get mixed results. Anyway, as per the hardhat starter kit that you linked, you can set the defaultNetwork to be 'hardhat' in the hardhat.config.js file, then when you deploy and run the integration tests (yarn test-integration), it will use mocks to mock up the VRF node, and to test the requesting of a random number. See the test here, and the mock contracts and linktoken get deployed here

Source https://stackoverflow.com/questions/69089799

QUESTION

How do I give my JSON schema an absolute URL for its $id when I haven't published it yet because it hasn't been tested yet?

Asked 2022-Mar-07 at 00:41

I'm putting together JSON schemas and I'd like to use $ref to DRY my schemas. I'll have many schemas that will each use common subschemas. I want to unit test my schemas before publishing them by writing unit tests that assert that, given certain input, the input is deemed valid or invalid, using a JSON schema library that I trust to be correct (so that I'm just testing my schemas, not the library).

Where I get confused is that in order to load my schemas before I've published them (which I want to do while running tests locally and during CI/CD), I need to use relative local paths like this:

1"pet": { "$ref": "file://./schemas/components/pet.schema.json" }
2

That's because that pet schema hasn't been published to a URL yet. It hasn't been verified by automated tests that it's correct yet. This works well enough for running tests, and it also worked well for packaging inside a Docker image so that the schemas could be loaded from disk as the app starts up.

But then, if I were to give one of the top level schemas to someone (that leverages $ref) after publishing it to an absolute URL, it wouldn't load in their program because of that path that I used that worked only for my unit testing.

I found that I had to publish my schemas using absolute URLs in order for them to be used in consuming programs. I ended up publishing the schemas https://mattwelke.github.io/go-jsonschema-ref-docker-example/schemas/person.1-0-0.schema.json and https://mattwelke.github.io/go-jsonschema-ref-docker-example/schemas/components/pet.1-0-0.schema.json that way. I tested that they worked fine in a consuming program by writing the program:

1"pet": { "$ref": "file://./schemas/components/pet.schema.json" }
2package main
3
4import (
5    "fmt"
6
7    "github.com/xeipuuv/gojsonschema"
8)
9
10func main() {
11    schemaLoader := gojsonschema.NewReferenceLoader("https://mattwelke.github.io/go-jsonschema-ref-docker-example/schemas/person.1-0-0.schema.json")
12
13    jsonStr := `
14    {
15        "name": "Matt",
16        "pet": {
17            "name": "Shady"
18        }
19    }
20    `
21
22    documentLoader := gojsonschema.NewStringLoader(jsonStr)
23
24    result, err := gojsonschema.Validate(schemaLoader, documentLoader)
25    if err != nil {
26        panic(fmt.Errorf("could not validate: %w", err))
27    }
28
29    if result.Valid() {
30        fmt.Printf("The document is valid.\n")
31    } else {
32        fmt.Printf("The document is not valid. See errors:\n")
33        for _, desc := range result.Errors() {
34            fmt.Printf("- %s\n", desc)
35        }
36    }
37}
38

Which resulted in the following expected output:

1"pet": { "$ref": "file://./schemas/components/pet.schema.json" }
2package main
3
4import (
5    "fmt"
6
7    "github.com/xeipuuv/gojsonschema"
8)
9
10func main() {
11    schemaLoader := gojsonschema.NewReferenceLoader("https://mattwelke.github.io/go-jsonschema-ref-docker-example/schemas/person.1-0-0.schema.json")
12
13    jsonStr := `
14    {
15        "name": "Matt",
16        "pet": {
17            "name": "Shady"
18        }
19    }
20    `
21
22    documentLoader := gojsonschema.NewStringLoader(jsonStr)
23
24    result, err := gojsonschema.Validate(schemaLoader, documentLoader)
25    if err != nil {
26        panic(fmt.Errorf("could not validate: %w", err))
27    }
28
29    if result.Valid() {
30        fmt.Printf("The document is valid.\n")
31    } else {
32        fmt.Printf("The document is not valid. See errors:\n")
33        for _, desc := range result.Errors() {
34            fmt.Printf("- %s\n", desc)
35        }
36    }
37}
38The document is valid.
39

So I'm confused about this "chicken and egg" situation.

I was able to publish schemas that could be used, as long as I didn't unit test them before publishing them.

And I was able to unit test schemas as long as:

  • I didn't want to publish them in the form that was verified by the unit testing to be correct.
  • I'm okay with my application loading them via HTTPS as it starts up instead of loading them from disk. I'm worried about this because I don't want a web server to be a point of failure for my app starting up.

I would appreciate some insight in how one might accomplish both goals.

ANSWER

Answered 2022-Mar-07 at 00:41

Where I get confused is that in order to load my schemas before I've published them (which I want to do while running tests locally and during CI/CD), I need to use relative local paths

Your initial assumption is false. URIs used in the $id keyword can be arbitrary identifiers -- they do not need to be resolvable via the network or disk at the stated location. In fact, it is an error for a JSON Schema implementation to assume to find schema documents at the stated location: they MUST support being able to load documents locally and associate them with the stated identifier:

The "$id" keyword identifies a schema resource with its canonical URI.

Note that this URI is an identifier and not necessarily a network locator. In the case of a network-addressable URL, a schema need not be downloadable from its canonical URI.

source

A schema need not be downloadable from the address if it is a network-addressable URL, and implementations SHOULD NOT assume they should perform a network operation when they encounter a network-addressable URI.

source

Therefore, you can give your schema document any identifier you like, such as the URI you anticipate using when you eventually publish your schema for public consumption, and perform local testing using that identifier.

Any implementation that does not support doing this is in violation of the specification, and this should be reported to its maintainers as a bug.

Source https://stackoverflow.com/questions/71374864

QUESTION

How to mock function without class in Kotlin?

Asked 2022-Feb-27 at 16:31
1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28

I am new to unit Testing, I want to know is there any way I can call MathUtils() function (inside Calculator class)

in MathUtilsSuccess() (inside CalculatorTest class) and i have to mock add() function which is not inside any class such that add() always returns 2, so that in success scenario my Test pass.

All the classes are in separate file and fun add() is also in separate file.

P.S : I have broken down my doubt into this simple example, This is not the actual problem i am working on.

ANSWER

Answered 2022-Feb-27 at 12:50

Indeed io.mockk:mockk supports to mock top-level functions in Kotlin.

Similar to extension functions, for top-level functions, Kotlin creates a class containing static functions under the hood as well, which in turn can be mocked.

However, you need to know the name of the underlying class created, which hints that probably this approach should only be used very rarely and with caution. I'll first demonstrate a working sample and name some alternative approaches afterwards.


Let's look at an example on how to mock a top-level function with MockK.

foo.kt

1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28package tld.domain.example
29
30fun foo(x: Int): Int = x + 3
31

bar.kt

1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28package tld.domain.example
29
30fun foo(x: Int): Int = x + 3
31package tld.domain.example
32
33fun bar(z: Int): Int = foo(z) + 2
34

You can mock static "things", such as extension functions, top-level functions and objects using mockkStatic.

1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28package tld.domain.example
29
30fun foo(x: Int): Int = x + 3
31package tld.domain.example
32
33fun bar(z: Int): Int = foo(z) + 2
34internal class BarKtTest {
35
36    @Test
37    internal fun `can work without mock`() {
38        unmockkAll() // just to show nothing is mocked anymore
39
40        val result = bar(1)
41
42        assertThat(result, equalTo(6))
43    }
44
45    @Test
46    internal fun `can be mocked`() {
47        mockkStatic("tld.domain.example.FooKt")
48        every { foo(any()) } returns 1
49
50        val result = bar(1)
51
52        assertThat(result, equalTo(3))
53    }
54}
55

As seen above, one is able to mock the top-level function yielding different results. The example above use com.natpryce:hamkrest for their assertions, but that should not matter.

When using IntelliJ, you can retrieve the name of the underlying class by using Tools > Kotlin > Show Kotlin Bytecode. In my example above, this yields a

1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28package tld.domain.example
29
30fun foo(x: Int): Int = x + 3
31package tld.domain.example
32
33fun bar(z: Int): Int = foo(z) + 2
34internal class BarKtTest {
35
36    @Test
37    internal fun `can work without mock`() {
38        unmockkAll() // just to show nothing is mocked anymore
39
40        val result = bar(1)
41
42        assertThat(result, equalTo(6))
43    }
44
45    @Test
46    internal fun `can be mocked`() {
47        mockkStatic("tld.domain.example.FooKt")
48        every { foo(any()) } returns 1
49
50        val result = bar(1)
51
52        assertThat(result, equalTo(3))
53    }
54}
55public final class tld/domain/example/FooKt {
56    ...
57

There is an overloaded version of mockkStatic that allows to provide a function reference instead of hard-coding the package name and class name as String. Note however, that this relies on the same methodology under the hood.

1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28package tld.domain.example
29
30fun foo(x: Int): Int = x + 3
31package tld.domain.example
32
33fun bar(z: Int): Int = foo(z) + 2
34internal class BarKtTest {
35
36    @Test
37    internal fun `can work without mock`() {
38        unmockkAll() // just to show nothing is mocked anymore
39
40        val result = bar(1)
41
42        assertThat(result, equalTo(6))
43    }
44
45    @Test
46    internal fun `can be mocked`() {
47        mockkStatic("tld.domain.example.FooKt")
48        every { foo(any()) } returns 1
49
50        val result = bar(1)
51
52        assertThat(result, equalTo(3))
53    }
54}
55public final class tld/domain/example/FooKt {
56    ...
57mockkStatic(::foo)
58

Instead of using static mocks, you could also make use of the dependency inversion principle, that is you inject the implementation of foo into bar somehow, e.g. through it's parameters or by wrapping it in a class containing a fields or using a higher level function.

1fun add() {
2    return 4+1;
3}
4
5
6class Calculator {
7    fun MathUtils() {
8        // do something
9        // calls add() function
10        val x: Int = add()
11
12        // return something
13        return x + 22
14    }
15}
16
17
18class CalculatorTest {
19    var c = Calculator()
20    
21    @Test
22    fun MathUtilsSuccess() {
23    Assertions.assertThat(
24            c.MathUtils()
25        ).isEqualTo(24)
26    }
27}
28package tld.domain.example
29
30fun foo(x: Int): Int = x + 3
31package tld.domain.example
32
33fun bar(z: Int): Int = foo(z) + 2
34internal class BarKtTest {
35
36    @Test
37    internal fun `can work without mock`() {
38        unmockkAll() // just to show nothing is mocked anymore
39
40        val result = bar(1)
41
42        assertThat(result, equalTo(6))
43    }
44
45    @Test
46    internal fun `can be mocked`() {
47        mockkStatic("tld.domain.example.FooKt")
48        every { foo(any()) } returns 1
49
50        val result = bar(1)
51
52        assertThat(result, equalTo(3))
53    }
54}
55public final class tld/domain/example/FooKt {
56    ...
57mockkStatic(::foo)
58fun barWithParam(foo: (Int) -> Int, z: Int): Int =
59    foo(z) + 2
60
61class BarProvider(private val foo: (Int) -> Int) {
62    fun bar(z: Int): Int = foo(z) + 2
63}
64
65fun barFactory(foo: (Int) -> Int): (Int) -> Int {
66    return { z -> foo(z) + 2 }
67}
68val bar = barFactory(::foo)
69

Another approach is to simply ignore the fact, that bar uses foo under the hood and tests the behaviour of bar without mocking foo. This mostly works, when foo is a pure function that does not have any side-effect, such as making any I/O operations, e.g. network, disk ...

Source https://stackoverflow.com/questions/71283136

QUESTION

What is the 'X' in this insert > X'3C2F756C3E'

Asked 2022-Feb-25 at 14:37

We have something similar to the following in the SQL that builds a test database for use with phpunit testing:

1INSERT (101, 23, 'test1', 'something', 0x3C2F756C3E)
2INSERT INTO `tableA` (`field1`, `field2`, `field3`, `field4`, `field5`)
3VALUES
4    (102, 23, 'test2', 'something', X'3C2F756C3E');
5

To my surprise this actually runs when I run it as a query and it inserts </ul> into field5.

I have tried searching for some info on the 'X' part but haven't found anything, I can see that there is something related to HTML entities here, but what is the 'X"? How does this work?

ANSWER

Answered 2022-Feb-25 at 14:37

The X signifies that the following is a hex-encoded binary string literal. It is defined in the ISO-9075-2:2016 SQL Standard as <binary string literal>:

1INSERT (101, 23, 'test1', 'something', 0x3C2F756C3E)
2INSERT INTO `tableA` (`field1`, `field2`, `field3`, `field4`, `field5`)
3VALUES
4    (102, 23, 'test2', 'something', X'3C2F756C3E');
5&lt;binary string literal&gt; ::=
6  X &lt;quote&gt; [ &lt;space&gt;... ] [ { &lt;hexit&gt; [ &lt;space&gt;... ] &lt;hexit&gt; [ &lt;space&gt;... ] }... ] &lt;quote&gt;
7    [ { &lt;separator&gt; &lt;quote&gt; [ &lt;space&gt;... ] [ { &lt;hexit&gt; [ &lt;space&gt;... ]
8    &lt;hexit&gt; [ &lt;space&gt;... ] }... ] &lt;quote&gt; }... ]
9
10&lt;hexit&gt; ::=
11  &lt;digit&gt; | A | B | C | D | E | F | a | b | c | d | e | f
12

The literal X'3C2F756C3E' when interpreted in ASCII or UTF-8 is:

  • 3C -> <
  • 2F -> /
  • 75 -> u
  • 6C -> l
  • 3E -> >

or </ul>.

See also the MySQL documentation, section Hexadecimal Literals (note: the MySQL syntax is more restrictive than the standard syntax, that is, MySQL does not allow spaces between hexits, nor splitting into multiple quote delimited sections).

Source https://stackoverflow.com/questions/71267183

QUESTION

Deploying Uniswap v2 / Sushiswap or similar in Brownie, Hardhat or Truffle test suite

Asked 2022-Feb-20 at 10:59

I am writing an automated test suite that needs to test functions against Uniswap v2 style automated market marker: do swaps and use different order routing. Thus, routers need to be deployed.

Are there any existing examples of how to deploy a testable Uniswap v2 style exchange in Brownie? Because Brownie is a minority of smart contract developers, are there any examples for Truffle or Hardhat?

I am also exploring the option of using a mainnet fork, but I am not sure if this operation is too expensive (slow) to be used in unit testing.

ANSWER

Answered 2022-Feb-10 at 14:30

Using a local testnet allows you to control very precisely the state of the blockchain during your test. However, it will require you to deploy every contract you need manually.

A fork of the mainnet will save you from having to deploy every contract already deployed on the mainnet. However you will sacrifice control over the environment and will require a connection to a node.

I've deployed Uniswap 2V on a testnet a few times. To do it you will need the bytecode and ABI for the following contracts: UniswapV2Factory, UniswapV2Pair, UniswapV2Router02 (I suppose you want the second version of the router). The Uniswap docs explains very well how to download them from NPM. For the router to work properly you will also need to deploy a WETH contract. I suggest deploying the one from this github page.

Before running this code, just make sure that your chain is running. For hardhat run the following command:

1npx hardhat node
2

Start by connecting your signer to your dev chain:

1npx hardhat node
2var provider = new ethers.providers.WebSocketProvider(&quot;ws://localhost:8545&quot;);
3var signer = provider.getSigner();
4

Using the ethers.js library, you first deploy the factory:

1npx hardhat node
2var provider = new ethers.providers.WebSocketProvider(&quot;ws://localhost:8545&quot;);
3var signer = provider.getSigner();
4const compiledUniswapFactory = require(&quot;@uniswap/v2-core/build/UniswapV2Factory.json&quot;);
5var uniswapFactory = await new ethers.ContractFactory(compiledUniswapFactory.interface,compiledUniswapFactory.bytecode,signer).deploy(await signer.getAddress());
6

Then the WETH contract:

1npx hardhat node
2var provider = new ethers.providers.WebSocketProvider(&quot;ws://localhost:8545&quot;);
3var signer = provider.getSigner();
4const compiledUniswapFactory = require(&quot;@uniswap/v2-core/build/UniswapV2Factory.json&quot;);
5var uniswapFactory = await new ethers.ContractFactory(compiledUniswapFactory.interface,compiledUniswapFactory.bytecode,signer).deploy(await signer.getAddress());
6const compiledWETH = require(&quot;canonical-weth/build/conrtacts/WETH.json&quot;;
7var WETH = await new ethers.ContractFactory(WETH.interface,WETH.bytecode,signer).deploy();
8

You can now deploy the router.

1npx hardhat node
2var provider = new ethers.providers.WebSocketProvider(&quot;ws://localhost:8545&quot;);
3var signer = provider.getSigner();
4const compiledUniswapFactory = require(&quot;@uniswap/v2-core/build/UniswapV2Factory.json&quot;);
5var uniswapFactory = await new ethers.ContractFactory(compiledUniswapFactory.interface,compiledUniswapFactory.bytecode,signer).deploy(await signer.getAddress());
6const compiledWETH = require(&quot;canonical-weth/build/conrtacts/WETH.json&quot;;
7var WETH = await new ethers.ContractFactory(WETH.interface,WETH.bytecode,signer).deploy();
8const compiledUniswapRouter = require(&quot;@uniswap/v2-periphery/build/UniswapV2Router02&quot;);
9var router = await new ethers.ContractFactory(compiledUniswapRouter.abi,compiledUniswapRouter.bytecode,signer).deploy(uniswapFactory.address,WETH.address);
10

You will also need to deploy the ERC20 tokens you need (Here is an example with tokens I've written):

1npx hardhat node
2var provider = new ethers.providers.WebSocketProvider(&quot;ws://localhost:8545&quot;);
3var signer = provider.getSigner();
4const compiledUniswapFactory = require(&quot;@uniswap/v2-core/build/UniswapV2Factory.json&quot;);
5var uniswapFactory = await new ethers.ContractFactory(compiledUniswapFactory.interface,compiledUniswapFactory.bytecode,signer).deploy(await signer.getAddress());
6const compiledWETH = require(&quot;canonical-weth/build/conrtacts/WETH.json&quot;;
7var WETH = await new ethers.ContractFactory(WETH.interface,WETH.bytecode,signer).deploy();
8const compiledUniswapRouter = require(&quot;@uniswap/v2-periphery/build/UniswapV2Router02&quot;);
9var router = await new ethers.ContractFactory(compiledUniswapRouter.abi,compiledUniswapRouter.bytecode,signer).deploy(uniswapFactory.address,WETH.address);
10const compiledERC20 = require(&quot;../../../Ethereum/Ethereum/sources/ERC20.sol/Token.json&quot;);
11var erc20Factory = new ethers.ContractFactory(compiledERC20.abi,compiledERC20.bytecode,signer);
12
13var erc20_0 = await erc20Factory.deploy(&quot;1000000&quot;, &quot;Token 0&quot;, &quot;5&quot;, &quot;T0&quot;);
14var erc20_1 = await erc20Factory.deploy(&quot;1000000&quot;, &quot;Token 1&quot;, &quot;5&quot;, &quot;T1&quot;);
15

The parameters of the deploy function will depend on the constructor of the token you wish to deploy.

You will also want to create pairs using the createPair method of the Uniswap factory.

1npx hardhat node
2var provider = new ethers.providers.WebSocketProvider(&quot;ws://localhost:8545&quot;);
3var signer = provider.getSigner();
4const compiledUniswapFactory = require(&quot;@uniswap/v2-core/build/UniswapV2Factory.json&quot;);
5var uniswapFactory = await new ethers.ContractFactory(compiledUniswapFactory.interface,compiledUniswapFactory.bytecode,signer).deploy(await signer.getAddress());
6const compiledWETH = require(&quot;canonical-weth/build/conrtacts/WETH.json&quot;;
7var WETH = await new ethers.ContractFactory(WETH.interface,WETH.bytecode,signer).deploy();
8const compiledUniswapRouter = require(&quot;@uniswap/v2-periphery/build/UniswapV2Router02&quot;);
9var router = await new ethers.ContractFactory(compiledUniswapRouter.abi,compiledUniswapRouter.bytecode,signer).deploy(uniswapFactory.address,WETH.address);
10const compiledERC20 = require(&quot;../../../Ethereum/Ethereum/sources/ERC20.sol/Token.json&quot;);
11var erc20Factory = new ethers.ContractFactory(compiledERC20.abi,compiledERC20.bytecode,signer);
12
13var erc20_0 = await erc20Factory.deploy(&quot;1000000&quot;, &quot;Token 0&quot;, &quot;5&quot;, &quot;T0&quot;);
14var erc20_1 = await erc20Factory.deploy(&quot;1000000&quot;, &quot;Token 1&quot;, &quot;5&quot;, &quot;T1&quot;);
15uniswapFactory.createPair(erc20_0.address,erc20_1.address);
16

Keep in mind that in the pair the tokens will be ordered arbitrarly by the contract. ERC20_0 might not be the first of the two.

After that just wait for all the transactions to go through and you should be good to start your test.

Source https://stackoverflow.com/questions/70846489

QUESTION

How to add unit testing in strapi version 4 using jest?

Asked 2022-Jan-25 at 19:26

I'm trying to add unit testing on a brand new strapi application. The official documentation is still in progress. So, until the documentation is being ready is there a way to add jest unit testing to strapi application ? i followed the approach in the v3 documentation with no luck.

ANSWER

Answered 2022-Jan-25 at 19:26

There are quite a few changes from Strapi V3 to Strapi V4 when it comes to initializing a Strapi application's APIs. The most important changes are how Strapi populates the KOA routes, and how to make requests to the http server.

To populate the KOA routes use

1await instance.server.mount();
2

instead of

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6

To call the http server use

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7

instead of

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8

You also need to use the new database configuration schema when defining your test database. You can use the following as an initial setup for your tests.

The following is an updated (and WIP) guide based on Strapi V3 Unit Testing guide.

First run

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9

or

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10

Then add the following to your ./package.json scripts:

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10&quot;scripts&quot;: {
11   // ...strapi scripts
12  &quot;test&quot;: &quot;jest --forceExit --detectOpenHandles&quot;, //add
13  &quot;watch&quot;: &quot;yarn test --watch&quot;, // optional
14}
15

Then add the following files:

./jest.config.js

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10&quot;scripts&quot;: {
11   // ...strapi scripts
12  &quot;test&quot;: &quot;jest --forceExit --detectOpenHandles&quot;, //add
13  &quot;watch&quot;: &quot;yarn test --watch&quot;, // optional
14}
15module.exports = {
16    verbose: true,
17    testPathIgnorePatterns: [
18        &quot;/node_modules/&quot;,
19        &quot;.tmp&quot;,
20        &quot;.cache&quot;
21    ],
22    modulePaths: [
23        &quot;/node_modules/&quot;,
24    ],
25    testEnvironment: &quot;node&quot;,
26};
27

./config/env/test/database.json

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10&quot;scripts&quot;: {
11   // ...strapi scripts
12  &quot;test&quot;: &quot;jest --forceExit --detectOpenHandles&quot;, //add
13  &quot;watch&quot;: &quot;yarn test --watch&quot;, // optional
14}
15module.exports = {
16    verbose: true,
17    testPathIgnorePatterns: [
18        &quot;/node_modules/&quot;,
19        &quot;.tmp&quot;,
20        &quot;.cache&quot;
21    ],
22    modulePaths: [
23        &quot;/node_modules/&quot;,
24    ],
25    testEnvironment: &quot;node&quot;,
26};
27{
28    &quot;connection&quot;: {
29        &quot;client&quot;: &quot;sqlite&quot;,
30        &quot;connection&quot;: {
31            &quot;filename&quot;: &quot;.tmp/test.db&quot;
32        },
33        &quot;useNullAsDefault&quot;: true,
34        &quot;pool&quot;: {
35            &quot;min&quot;: 0,
36            &quot;max&quot;: 1
37        }
38    }
39}
40

./tests/helpers/strapi.js

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10&quot;scripts&quot;: {
11   // ...strapi scripts
12  &quot;test&quot;: &quot;jest --forceExit --detectOpenHandles&quot;, //add
13  &quot;watch&quot;: &quot;yarn test --watch&quot;, // optional
14}
15module.exports = {
16    verbose: true,
17    testPathIgnorePatterns: [
18        &quot;/node_modules/&quot;,
19        &quot;.tmp&quot;,
20        &quot;.cache&quot;
21    ],
22    modulePaths: [
23        &quot;/node_modules/&quot;,
24    ],
25    testEnvironment: &quot;node&quot;,
26};
27{
28    &quot;connection&quot;: {
29        &quot;client&quot;: &quot;sqlite&quot;,
30        &quot;connection&quot;: {
31            &quot;filename&quot;: &quot;.tmp/test.db&quot;
32        },
33        &quot;useNullAsDefault&quot;: true,
34        &quot;pool&quot;: {
35            &quot;min&quot;: 0,
36            &quot;max&quot;: 1
37        }
38    }
39}
40const Strapi = require(&quot;@strapi/strapi&quot;);
41const fs = require(&quot;fs&quot;);
42
43let instance;
44
45async function setupStrapi() {
46  if (!instance) {
47    await Strapi().load();
48    instance = strapi;
49    await instance.server.mount();
50  }
51  return instance;
52}
53
54async function cleanupStrapi() {
55  const dbSettings = strapi.config.get(&quot;database.connection&quot;);
56  const tmpDbFile = dbSettings.connection.filename
57
58  //close server to release the db-file
59  await strapi.server.httpServer.close();
60
61  //delete test database after all tests
62  if (dbSettings &amp;&amp; tmpDbFile) {
63    if (fs.existsSync(tmpDbFile)) {
64      fs.unlinkSync(tmpDbFile);
65    }
66  }
67  // close the connection to the database
68  await strapi.db.connection.destroy();
69}
70
71module.exports = { setupStrapi, cleanupStrapi };
72

Note that you need to have the /hello endpoint in your project as specified in the strapi docs for the next tests to pass.

./tests/app.test.js

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10&quot;scripts&quot;: {
11   // ...strapi scripts
12  &quot;test&quot;: &quot;jest --forceExit --detectOpenHandles&quot;, //add
13  &quot;watch&quot;: &quot;yarn test --watch&quot;, // optional
14}
15module.exports = {
16    verbose: true,
17    testPathIgnorePatterns: [
18        &quot;/node_modules/&quot;,
19        &quot;.tmp&quot;,
20        &quot;.cache&quot;
21    ],
22    modulePaths: [
23        &quot;/node_modules/&quot;,
24    ],
25    testEnvironment: &quot;node&quot;,
26};
27{
28    &quot;connection&quot;: {
29        &quot;client&quot;: &quot;sqlite&quot;,
30        &quot;connection&quot;: {
31            &quot;filename&quot;: &quot;.tmp/test.db&quot;
32        },
33        &quot;useNullAsDefault&quot;: true,
34        &quot;pool&quot;: {
35            &quot;min&quot;: 0,
36            &quot;max&quot;: 1
37        }
38    }
39}
40const Strapi = require(&quot;@strapi/strapi&quot;);
41const fs = require(&quot;fs&quot;);
42
43let instance;
44
45async function setupStrapi() {
46  if (!instance) {
47    await Strapi().load();
48    instance = strapi;
49    await instance.server.mount();
50  }
51  return instance;
52}
53
54async function cleanupStrapi() {
55  const dbSettings = strapi.config.get(&quot;database.connection&quot;);
56  const tmpDbFile = dbSettings.connection.filename
57
58  //close server to release the db-file
59  await strapi.server.httpServer.close();
60
61  //delete test database after all tests
62  if (dbSettings &amp;&amp; tmpDbFile) {
63    if (fs.existsSync(tmpDbFile)) {
64      fs.unlinkSync(tmpDbFile);
65    }
66  }
67  // close the connection to the database
68  await strapi.db.connection.destroy();
69}
70
71module.exports = { setupStrapi, cleanupStrapi };
72const { setupStrapi, cleanupStrapi } = require(&quot;./helpers/strapi&quot;);
73
74jest.setTimeout(15000);
75
76beforeAll(async () =&gt; {
77  await setupStrapi(); 
78});
79
80afterAll(async () =&gt; {
81 await cleanupStrapi();
82});
83
84it(&quot;strapi is defined&quot;, () =&gt; {
85  expect(strapi).toBeDefined();
86});
87
88require('./hello')
89

./tests/hello/index.js

1await instance.server.mount();
2await instance.app
3       .use(instance.router.routes()) // populate KOA routes
4       .use(instance.router.allowedMethods()); // populate KOA methods
5instance.server = http.createServer(instance.app.callback());
6 strapi.server.httpServer
7 strapi.server
8 yarn add --dev jest supertest sqlite3
9 npm install --save-dev jest supertest sqlite3
10&quot;scripts&quot;: {
11   // ...strapi scripts
12  &quot;test&quot;: &quot;jest --forceExit --detectOpenHandles&quot;, //add
13  &quot;watch&quot;: &quot;yarn test --watch&quot;, // optional
14}
15module.exports = {
16    verbose: true,
17    testPathIgnorePatterns: [
18        &quot;/node_modules/&quot;,
19        &quot;.tmp&quot;,
20        &quot;.cache&quot;
21    ],
22    modulePaths: [
23        &quot;/node_modules/&quot;,
24    ],
25    testEnvironment: &quot;node&quot;,
26};
27{
28    &quot;connection&quot;: {
29        &quot;client&quot;: &quot;sqlite&quot;,
30        &quot;connection&quot;: {
31            &quot;filename&quot;: &quot;.tmp/test.db&quot;
32        },
33        &quot;useNullAsDefault&quot;: true,
34        &quot;pool&quot;: {
35            &quot;min&quot;: 0,
36            &quot;max&quot;: 1
37        }
38    }
39}
40const Strapi = require(&quot;@strapi/strapi&quot;);
41const fs = require(&quot;fs&quot;);
42
43let instance;
44
45async function setupStrapi() {
46  if (!instance) {
47    await Strapi().load();
48    instance = strapi;
49    await instance.server.mount();
50  }
51  return instance;
52}
53
54async function cleanupStrapi() {
55  const dbSettings = strapi.config.get(&quot;database.connection&quot;);
56  const tmpDbFile = dbSettings.connection.filename
57
58  //close server to release the db-file
59  await strapi.server.httpServer.close();
60
61  //delete test database after all tests
62  if (dbSettings &amp;&amp; tmpDbFile) {
63    if (fs.existsSync(tmpDbFile)) {
64      fs.unlinkSync(tmpDbFile);
65    }
66  }
67  // close the connection to the database
68  await strapi.db.connection.destroy();
69}
70
71module.exports = { setupStrapi, cleanupStrapi };
72const { setupStrapi, cleanupStrapi } = require(&quot;./helpers/strapi&quot;);
73
74jest.setTimeout(15000);
75
76beforeAll(async () =&gt; {
77  await setupStrapi(); 
78});
79
80afterAll(async () =&gt; {
81 await cleanupStrapi();
82});
83
84it(&quot;strapi is defined&quot;, () =&gt; {
85  expect(strapi).toBeDefined();
86});
87
88require('./hello')
89const request = require('supertest');
90
91it('should return hello world', async () =&gt; {
92  await request(strapi.server.httpServer) 
93    .get('/api/hello')
94    .expect(200) // Expect response http code 200
95});
96

I hope this helps anyone struggling with the same issues. I will update the answer as I progress.

Source https://stackoverflow.com/questions/70283992

QUESTION

What exactly is/means &quot;System.IO.Stream+NullStream&quot;?

Asked 2022-Jan-24 at 13:44

I am currently experimenting to find the proper way of creating an HTTP context for unit testing purposes. While examining the stream types created, I was surprised that the following returns a type of System.IO.Stream+NullStream.

1var context = new DefaultHttpContext();
2
3var requestBodyType = context.Request.Body.GetType().FullName; 
4var responseBodyType = context.Response.Body.GetType().FullName; 
5

If the test case requires it, I'd simply replace the stream with a MemoryStream and then act upon it accordingly.

1var context = new DefaultHttpContext();
2
3var requestBodyType = context.Request.Body.GetType().FullName; 
4var responseBodyType = context.Response.Body.GetType().FullName; 
5var memoryStream = new MemoryStream();
6var context = new DefaultHttpContext(); 
7context.Response.Body = memoryStream;
8

So far so good. But what exactly is System.IO.Stream+NullStream? I would have expected to find a type of NullStream in the documentation, but couldn't find such a thing.

ANSWER

Answered 2022-Jan-24 at 13:33

It's an internal type.

It sub-classes Stream, and is exposed as Stream.Null.

As you can see from the implementation, it just throws away any data written to it, and doesn't return any data if asked.

Source https://stackoverflow.com/questions/70834632

QUESTION

Unit testing SwiftUI/Combine @Published boolean values

Asked 2022-Jan-23 at 00:46

I am trying to acquaint myself with unit testing some view models in SwiftUI. The view model currently has two @Published boolean values that publish changes when an underlying UserDefaults property changes. For my unit tests, I have followed this guide on how to setup UserDefaults for testing so my production values are not modified. I am able to test the default value as such:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4

How would I go about toggling the @Published value then ensuring my view model has received the changes? So for instance, I have a reference to my mock user defaults in my XCTestCase. I attempted to do the following with zero success:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4func testValueTogglesToTrue() {
5     defaults.canDoThing = true
6     XCTAssertTrue(viewModel.canDoThing)
7

}

The thought being that updating the underlying user defaults value that is publishing changes to the published value in the view model will notify our view model. The above does not do anything to the view model variable. Do I need to subscribe to the publisher and use sink to accomplish this?

ANSWER

Answered 2022-Jan-22 at 16:07

Let's say you store a flag in UserDefaults to know whether the user has completed onboarding:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4func testValueTogglesToTrue() {
5     defaults.canDoThing = true
6     XCTAssertTrue(viewModel.canDoThing)
7extension UserDefaults {
8
9    @objc dynamic public var completedOnboarding: Bool {
10        bool(forKey: &quot;completedOnboarding&quot;)
11    }
12}
13

You have a ViewModel which tells your View whether to show onboarding or not and has a method to mark onboarding as completed:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4func testValueTogglesToTrue() {
5     defaults.canDoThing = true
6     XCTAssertTrue(viewModel.canDoThing)
7extension UserDefaults {
8
9    @objc dynamic public var completedOnboarding: Bool {
10        bool(forKey: &quot;completedOnboarding&quot;)
11    }
12}
13class ViewModel: ObservableObject {
14    
15    @Published private(set) var showOnboarding: Bool = true
16    
17    private let userDefaults: UserDefaults
18    
19    public init(userDefaults: UserDefaults) {
20        self.userDefaults = userDefaults
21        self.showOnboarding = !userDefaults.completedOnboarding
22        userDefaults
23            .publisher(for: \.completedOnboarding)
24            .map { !$0 }
25            .receive(on: RunLoop.main)
26            .assign(to: &amp;$showOnboarding)
27    }
28    
29    public func completedOnboarding() {
30        userDefaults.set(true, forKey: &quot;completedOnboarding&quot;)
31    }
32}
33

To test this class you have a XCTestCase:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4func testValueTogglesToTrue() {
5     defaults.canDoThing = true
6     XCTAssertTrue(viewModel.canDoThing)
7extension UserDefaults {
8
9    @objc dynamic public var completedOnboarding: Bool {
10        bool(forKey: &quot;completedOnboarding&quot;)
11    }
12}
13class ViewModel: ObservableObject {
14    
15    @Published private(set) var showOnboarding: Bool = true
16    
17    private let userDefaults: UserDefaults
18    
19    public init(userDefaults: UserDefaults) {
20        self.userDefaults = userDefaults
21        self.showOnboarding = !userDefaults.completedOnboarding
22        userDefaults
23            .publisher(for: \.completedOnboarding)
24            .map { !$0 }
25            .receive(on: RunLoop.main)
26            .assign(to: &amp;$showOnboarding)
27    }
28    
29    public func completedOnboarding() {
30        userDefaults.set(true, forKey: &quot;completedOnboarding&quot;)
31    }
32}
33class MyTestCase: XCTestCase {
34    
35    private var userDefaults: UserDefaults!
36    private var cancellables = Set&lt;AnyCancellable&gt;()
37    
38    override func setUpWithError() throws {
39        try super.setUpWithError()
40        userDefaults = try XCTUnwrap(UserDefaults(suiteName: #file))
41        userDefaults.removePersistentDomain(forName: #file)
42    }
43
44    // ...
45}
46

Some of the test cases are synchronous for example you can easily test that showOnboarding depends on UserDefaults completedOnboarding property:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4func testValueTogglesToTrue() {
5     defaults.canDoThing = true
6     XCTAssertTrue(viewModel.canDoThing)
7extension UserDefaults {
8
9    @objc dynamic public var completedOnboarding: Bool {
10        bool(forKey: &quot;completedOnboarding&quot;)
11    }
12}
13class ViewModel: ObservableObject {
14    
15    @Published private(set) var showOnboarding: Bool = true
16    
17    private let userDefaults: UserDefaults
18    
19    public init(userDefaults: UserDefaults) {
20        self.userDefaults = userDefaults
21        self.showOnboarding = !userDefaults.completedOnboarding
22        userDefaults
23            .publisher(for: \.completedOnboarding)
24            .map { !$0 }
25            .receive(on: RunLoop.main)
26            .assign(to: &amp;$showOnboarding)
27    }
28    
29    public func completedOnboarding() {
30        userDefaults.set(true, forKey: &quot;completedOnboarding&quot;)
31    }
32}
33class MyTestCase: XCTestCase {
34    
35    private var userDefaults: UserDefaults!
36    private var cancellables = Set&lt;AnyCancellable&gt;()
37    
38    override func setUpWithError() throws {
39        try super.setUpWithError()
40        userDefaults = try XCTUnwrap(UserDefaults(suiteName: #file))
41        userDefaults.removePersistentDomain(forName: #file)
42    }
43
44    // ...
45}
46func test_whenCompletedOnboardingFalse_thenShowOnboardingTrue() {
47    userDefaults.set(false, forKey: &quot;completedOnboarding&quot;)
48    let subject = ViewModel(userDefaults: userDefaults)
49    XCTAssert(subject.showOnboarding)
50}
51    
52func test_whenCompletedOnboardingTrue_thenShowOnboardingFalse() {
53    userDefaults.set(true, forKey: &quot;completedOnboarding&quot;)
54    let subject = ViewModel(userDefaults: userDefaults)
55    XCTAssertFalse(subject.showOnboarding)
56}
57

Some test are asynchronous, which means you need to use XCTExpectations to wait for the @Published value to change:

1func testDefaultValue() {
2     XCTAssertFalse(viewModel.canDoThing)
3}
4func testValueTogglesToTrue() {
5     defaults.canDoThing = true
6     XCTAssertTrue(viewModel.canDoThing)
7extension UserDefaults {
8
9    @objc dynamic public var completedOnboarding: Bool {
10        bool(forKey: &quot;completedOnboarding&quot;)
11    }
12}
13class ViewModel: ObservableObject {
14    
15    @Published private(set) var showOnboarding: Bool = true
16    
17    private let userDefaults: UserDefaults
18    
19    public init(userDefaults: UserDefaults) {
20        self.userDefaults = userDefaults
21        self.showOnboarding = !userDefaults.completedOnboarding
22        userDefaults
23            .publisher(for: \.completedOnboarding)
24            .map { !$0 }
25            .receive(on: RunLoop.main)
26            .assign(to: &amp;$showOnboarding)
27    }
28    
29    public func completedOnboarding() {
30        userDefaults.set(true, forKey: &quot;completedOnboarding&quot;)
31    }
32}
33class MyTestCase: XCTestCase {
34    
35    private var userDefaults: UserDefaults!
36    private var cancellables = Set&lt;AnyCancellable&gt;()
37    
38    override func setUpWithError() throws {
39        try super.setUpWithError()
40        userDefaults = try XCTUnwrap(UserDefaults(suiteName: #file))
41        userDefaults.removePersistentDomain(forName: #file)
42    }
43
44    // ...
45}
46func test_whenCompletedOnboardingFalse_thenShowOnboardingTrue() {
47    userDefaults.set(false, forKey: &quot;completedOnboarding&quot;)
48    let subject = ViewModel(userDefaults: userDefaults)
49    XCTAssert(subject.showOnboarding)
50}
51    
52func test_whenCompletedOnboardingTrue_thenShowOnboardingFalse() {
53    userDefaults.set(true, forKey: &quot;completedOnboarding&quot;)
54    let subject = ViewModel(userDefaults: userDefaults)
55    XCTAssertFalse(subject.showOnboarding)
56}
57func test_whenCompleteOnboardingCalled_thenShowOnboardingFalse() {
58    let subject = ViewModel(userDefaults: userDefaults)
59    // first define the expectation that showOnboarding will change to false (1)
60    let showOnboardingFalse = expectation(
61        description: &quot;when completedOnboarding called then show onboarding is false&quot;)
62        
63    // subscribe to showOnboarding publisher to know when the value changes (2)
64    subject
65        .$showOnboarding
66        .filter { !$0 }
67        .sink { _ in
68            // when false received fulfill the expectation (5)
69            showOnboardingFalse.fulfill()
70        }
71        .store(in: &amp;cancellables)
72        
73    // trigger the function that changes the value (3)
74    subject.completedOnboarding()
75    // tell the tests to wait for your expectation (4)
76    waitForExpectations(timeout: 0.1)
77}
78

Source https://stackoverflow.com/questions/70809030

Community Discussions contain sources that include Stack Exchange Network

Tutorials and Learning Resources in Unit Testing

Tutorials and Learning Resources are not available at this moment for Unit Testing

Share this Page

share link

Get latest updates on Unit Testing