Cookie Consent by Free Privacy Policy Generator ๐Ÿ“Œ Test Doubles: A Quick Guide to Boost Your Testing Skills

๐Ÿ  Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeitrรคge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden รœberblick รผber die wichtigsten Aspekte der IT-Sicherheit in einer sich stรคndig verรคndernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch รผbersetzen, erst Englisch auswรคhlen dann wieder Deutsch!

Google Android Playstore Download Button fรผr Team IT Security



๐Ÿ“š Test Doubles: A Quick Guide to Boost Your Testing Skills


๐Ÿ’ก Newskategorie: Programmierung
๐Ÿ”— Quelle: dev.to

Welcome to the fast-paced realm of software development, where mastering Test Doubles is your key to crafting rock-solid
code and easing your way to TDD mastery. In just a few seconds, we'll unravel the secrets of spies, stubs, and fakes,
exploring their power to supercharge your testing game. Whether you're a TDD veteran or a newcomer, join us on this
quick journey to transform your approach to testing and elevate our code quality.

Doubles come into play when you prefer not to employ a specific implementation of an interface in your tests,
streamlining the test-writing process and speeding up feedback on actual features. They prove valuable in ensuring test
independence from infrastructure, such as crafting Doubles for a Repository and contributing to more effective and
efficient testing.

Dummy

Dummies are services that our SUT (System Under Test) depends on but are irrelevant to the test scope.

Example with a banking account creation feature relying on a BankingAccountRepository as well as an EventPublisher and
our current tests do not have any concern for the event publisher. We can just replace it with a Dummy implementation
that will not affect our testing system.

class CreateBankingAccount {
    constructor(
        private readonly _bankingAccountRepository: BankingAccountRepository,
        private readonly _eventPublisher: EventPublisher
    ) {
    }

    execute() {
        //Some business logic and references to _eventPublisher
    }
}

interface EventPublisher {
    publish(event: Event): void
}

class DummyEventPublisher implements EventPublisher {
    publish(event: Event): void {
        // Do nothing, we call it a dummy implementation
    }
}

Spy

A test spy is a tool that captures indirect output and provides necessary indirect input, dealing with output that is
not directly observable.

In the given code snippet, we obtain detailed information about "published" events. This is especially valuable in an
event-driven system where you need or must publish events on a bus without yet knowing the subsequent actions they may
trigger.

The key motivation behind employing a spy is to gain a more in-depth insight into the internal state of the system, even
though this comes at the expense of heightened coupling.

it("publishes a banking account event", () => {
    const spy = new SpyEventPublisher();
    const useCase = new CreateBankingAccount(bankingAccountRepository, spy);

    useCase.execute();

    expect(spy.events.length).toEqual(1);
    expect(spy.events[0]).toEqual({id: "newBankingAccountId"});
})

class SpyEventPublisher implements EventPublisher {
    private readonly _events: Array<Event> = []

    publish(event: Event): void {
        this._events.push(event)
    }

    get events() {
        return this._events
    }
}

class CreateBankingAccount {
    constructor(
        private readonly _bankingAccountRepository: BankingAccountRepository,
        private readonly _eventPublisher: EventPublisher
    ) {
    }

    execute() {
        //Some business logic
        this._eventPublisher.publish({id: "newBankingAccountId"})
    }
}

Stub

A stub is an object that returns fake data injected into it.

Consider a scenario where our feature relies on an external API to fetch user data, such as a credit score needed for
creating an account. To ensure the service functions as expected, we can build a stub object with fake values.

The following snippet represents a potential implementation of a stub for the external API.

interface UserDataGateway {
    creditScore(email: string): number
}

class StubUserDataGateway implements UserDataGateway {
    private _creditScoreValue: number

    creditScore(email: string): number {
        return this._creditScoreValue;
    }

    set creditScoreValue(value: number) {
        this._creditScoreValue = value;
    }
}

Then our test would look like:

it("requires a positive credit score to create a bank account", async () => {
    const stub = new StubUserDataGateway();
    const useCase = new CreateBankingAccount(bankingAccountRepository, new DummyEventPublisher());
    {
        stub.creditScoreValue = 0
        useCase.execute({email: "[email protected]"});
        expect(bankingAccountRepository.accounts).toEqual([]);
    }
    {
        stub.creditScoreValue = 20
        useCase.execute({email: "[email protected]"});
        expect(bankingAccountRepository.accounts).toEqual([/*An account object*/]);
    }
})

class CreateBankingAccount {
    constructor(
        private readonly _bankingAccountRepository: BankingAccountRepository,
        private readonly _userDataGateway: UserDataGateway
    ) {
    }

    execute({email}: { email: string }) {
        if (!this._userDataGateway.creditScore(email)) return
        // Bank account creation logic
    }
}

I'm confident you've already noticed a flaw in this design. The issue lies in the fact that we could replace the email
with any string in the statement below, because of our Stub implementation.

this._userDataGateway.creditScore(email)

This is why, most of the time, we prefer to add a touch of simple logic rather than keeping it entirely straightforward,
as you can see in the following code snippet.

class StubUserDataGateway implements UserDataGateway {
    private _creditScores: { [email: string]: number } = {}

    creditScore(email: string): number {
        return this._creditScores[email] || 0;
    }

    feedWith(email, creditScore) {
        this._creditScores[email] = creditScore;
    }
}

Leading our test implementation to

it("requires a positive credit score to create a bank account", async () => {
    const stub = new StubUserDataGateway();
    const useCase = new CreateBankingAccount(bankingAccountRepository, new DummyEventPublisher());
    {
        stub.feedWith("[email protected]", 0)
        useCase.execute({email: "[email protected]"});
        expect(bankingAccountRepository.accounts).toEqual([]);
    }
    {
        stub.feedWith("[email protected]", 1)
        useCase.execute({email: "[email protected]"});
        expect(bankingAccountRepository.accounts).toEqual([/*An account object*/]);
    }
})

Fake

Last but not least, Fakes! They are primarily used when we want to implement an architectural interface with some
in-memory logic, so we are not bound to an external infrastructure service like a Database for example. Depending on its
implementation, but most of the time, a fake implementation can be used in a production-like environment for demo
purposes.

The following snippet represents a simple but common Fake implementation of a repository in a trivial system:

class InMemoryBankingAccountRepository implements BankingAccountRepository {
    private readonly _accounts: Array<BankingAccount> = []

    create(bankingAccount: BankingAccount) {
        this._accounts.push(bankingAccount)
    }


    get accounts(): Array<BankingAccount> {
        return this._accounts;
    }
}


it("creates an account", async () => {
    const repository = new InMemoryBankingAccountRepository()
    const useCase = new CreateBankingAccount(bankingAccountRepository)

    useCase.execute({accountId: "someAccountId"})

    expect(repository.accounts).toEqual([{accountId: "someAccountId"}])
})

In future articles, we will dive deeper into these concepts and apply them in real-world applications.

Stay tuned, and feel free to follow me on this platform and
on LinkedIn, where I share insights every week about software
design, OOP practices, discoveries, and my projects! ๐Ÿ’ป๐Ÿ„

...



๐Ÿ“Œ Test Doubles: A Quick Guide to Boost Your Testing Skills


๐Ÿ“ˆ 67.64 Punkte

๐Ÿ“Œ Elevate Your Testing Skills: Advanced API Functional Testing Methods


๐Ÿ“ˆ 28.29 Punkte

๐Ÿ“Œ 10 Must-Read Books for Every Programmer: Boost Your Skills and Advance Your Career!


๐Ÿ“ˆ 26.89 Punkte

๐Ÿ“Œ Quick test: Are you using all the DevOps testing tactics in your toolkit?


๐Ÿ“ˆ 24.08 Punkte

๐Ÿ“Œ Boost your career by developing Excel skills from beginner to advanced for just $35


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ Want to boost your cyber security skills by playing games this Christmas?


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ How to Use ESLint to Boost Your Programming Skills


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ From padawan to Jedi - boost your dev skills with the Ultimate Todo App


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ 10 Tmux & SSH Tips to Boost Your Remote Development Skills


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ 2 Tasks to Boost Your Python Data Wrangling Skills


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ How to boost your Excel skills with Copilot | Excel in Copilot Tutorial


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ Practical ways to boost Your Reading Skills


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ How to Boost Your Reading Skills with Dictozo


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ Seize the chance to boost your IT security skills: Trio of training events to choose from


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ Seize the chance to boost your IT security skills: SANS London has plenty of courses for you


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ Boost your IT skills with a Windows PowerShell bootcamp for $20


๐Ÿ“ˆ 23.4 Punkte

๐Ÿ“Œ A Quick Guide to Penetration Testing


๐Ÿ“ˆ 23.38 Punkte

๐Ÿ“Œ Node.js Unit Testing with Jest: A Quick Guide


๐Ÿ“ˆ 23.38 Punkte

๐Ÿ“Œ Performance Testing vs. Load Testing vs. Stress Testing


๐Ÿ“ˆ 22.19 Punkte

๐Ÿ“Œ Load testing your test engines with Azure Load Testing


๐Ÿ“ˆ 21.95 Punkte

๐Ÿ“Œ Beginner Guide on Unit Testing in React using React Testing Library and Vitest


๐Ÿ“ˆ 21.26 Punkte

๐Ÿ“Œ Effortless UI Testing with CircleCI and Cypress Integration: A Guide to Testing Components and Functionality on a Website


๐Ÿ“ˆ 21.26 Punkte

๐Ÿ“Œ Guide to Serverless & Lambda Testing โ€” Part 2 โ€” Testing Pyramid


๐Ÿ“ˆ 21.26 Punkte

๐Ÿ“Œ Learn Live - Supercharge your DevOps skills with Azure Load Testing


๐Ÿ“ˆ 20.89 Punkte

๐Ÿ“Œ Jest Mastery: Elevating Your Testing Skills with Proven Best Practices


๐Ÿ“ˆ 20.89 Punkte

๐Ÿ“Œ New Battery DOUBLES Range of Tesla Model S in Road Test


๐Ÿ“ˆ 20.86 Punkte

๐Ÿ“Œ Go Test Doubles by Example


๐Ÿ“ˆ 20.86 Punkte

๐Ÿ“Œ Facebook doubles cooling off period to cash in on your FOMO


๐Ÿ“ˆ 20.66 Punkte

๐Ÿ“Œ Apple doubles the lifespan of your iPhone 15's battery, no update required


๐Ÿ“ˆ 20.66 Punkte

๐Ÿ“Œ This new eBay AI feature doubles as your personal shopper. Here's how to get started


๐Ÿ“ˆ 20.66 Punkte

๐Ÿ“Œ Facebook doubles down on misusing your phone number


๐Ÿ“ˆ 20.66 Punkte

๐Ÿ“Œ Kensington's LD5400T docking station doubles as a guardian for your laptop


๐Ÿ“ˆ 20.66 Punkte

๐Ÿ“Œ Workday Debuts a Universal Skills Ontology Called Skills Cloud


๐Ÿ“ˆ 20.01 Punkte











matomo