Home > Software design >  Flutter: testing with custom model
Flutter: testing with custom model

Time:01-03

Im trying to get tests working in flutter. Right now Im trying to use firebase mockAuth and fakeFirestore to simulate signing up and creatiing a user document, which looks like hits:

import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';
import 'package:firebase_auth_mocks/firebase_auth_mocks.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_test/flutter_test.dart';

//import AuthRepository
import 'package:hero/repository/auth_repository.dart';

import '../models/user_model.dart';

void main() {
  testWidgets('My app has a title and message', (WidgetTester tester) async {
    
    //make a material app and do Firebase.initializeApp()

    final mockAuth = MockFirebaseAuth();
    //make the fake firestore instance
    final mockFirestore = FakeFirebaseFirestore();
    final cred = await mockAuth.createUserWithEmailAndPassword(
      email: '[email protected]',
      password: 'password',
    );

    final user = AuthRepository().userFromFirebaseUser(cred.user);

    await mockFirestore.collection('users').doc(user!.id).set(
          User.toJson(user),
        );
  });
}

However, when I add the last line with my custom User class, i get alot of errors that look like

ib/repository/storage_repository.dart:9:8: Error: Error when reading '/models/models.dart': No such file or directory
import '/models/models.dart';

And the user model is as follows: be warned, its alot of boilerplate:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';
import 'package:hero/models/stingray_model.dart';
//import firebase

import '../screens/onboarding/onboarding_screens/birthDate_screen.dart';
import 'chat_model.dart';
import 'team_model.dart';

class User extends Equatable {
  final String? id;
  final String name;
  final int age;
  final List<dynamic> imageUrls;
  final List<dynamic> interests;
  final String bio;
  final String jobTitle;
  final String gender;
  final bool isStingray;
  final String? email;
  final Team? team;
  final int votes;
  final int votesUsable;
  final int instigations;
  final bool isRude;
  final List<dynamic> stingrays;
  final bool finishedOnboarding;
  final String handle;
  final List<Chat?> chats;
  final bool newMessages;
  final List<dynamic> goals;
  final DateTime birthDate;
  final bool isAdmin;
  final bool receivedSecretVote;
  final bool wantsToTalk;
  final int discoveriesRemaning;
  final String typsenseId;
  final int randomInt;
  final bool isBanned;
  final String banReason;
  final DateTime banExpiration;
  final bool seenWaveLikeNotification;
  final bool seenVoteNotification;
  final bool verified;
  final bool seenTutorial;
  final bool castFirstVote;
  final bool newNotifications;
  final List<dynamic> blockedBy;
  final List<dynamic> blockedUsers;
  final List<dynamic> blockedUserIds;
  final DateTime? createdAt;
  final bool isPup;

  const User({
    required this.id,
    required this.name,
    required this.age,
    required this.imageUrls,
    required this.interests,
    required this.bio,
    required this.gender,
    required this.jobTitle,
    this.isStingray = false,
    this.email = 'bruh',
    this.team = null,
    required this.instigations,
    required this.isRude,
    required this.votes,
    required this.votesUsable,
    required this.stingrays,
    required this.finishedOnboarding,
    required this.chats,
    required this.handle,
    required this.newMessages,
    required this.goals,
    required this.birthDate,
    required this.isAdmin,
    required this.receivedSecretVote,
    required this.wantsToTalk,
    required this.discoveriesRemaning,
    required this.typsenseId,
    required this.randomInt,
    required this.isBanned,
    required this.banReason,
    required this.banExpiration,
    required this.seenWaveLikeNotification,
    required this.seenVoteNotification,
    required this.verified,
    required this.seenTutorial,
    required this.castFirstVote,
    required this.newNotifications,
    required this.blockedBy,
    required this.blockedUsers,
    required this.blockedUserIds,
    required this.createdAt,
    required this.isPup,
  });

  @override
  List<Object?> get props => [
        id,
        name,
        age,
        imageUrls,
        bio,
        jobTitle,
        isStingray,
        email,
        team,
        instigations,
        isRude,
        votes,
        votesUsable,
        stingrays,
        finishedOnboarding,
        interests,
        instigations,
        handle,
        chats,
        newMessages,
        goals,
        birthDate,
        isAdmin,
        receivedSecretVote,
        wantsToTalk,
        discoveriesRemaning,
        typsenseId,
        randomInt,
        isBanned,
        banReason,
        banExpiration,
        seenWaveLikeNotification,
        seenVoteNotification,
        verified,
        seenTutorial,
        castFirstVote,
        newNotifications,
        blockedBy,
        blockedUsers,
        blockedUserIds,
        createdAt,
        isPup,
      ];

  static Map<String, dynamic> toJson(User? user) => {
        'id': user?.id,
        'name': user?.name,
        'age': user?.age,
        'imageUrls': user?.imageUrls,
        'interests': user?.interests,
        'bio': user?.bio,
        'jobTitle': user?.jobTitle,
        'isStingray': user?.isStingray,
        'instigations': user?.instigations,
        'isRude': user?.isRude,
        'votes': user?.votes,
        'votesUsable': user?.votesUsable,
        'stingrays': user?.stingrays,
        'finishedOnboarding': user?.finishedOnboarding,
        'gender': user?.gender,
        'handle': user?.handle,
        'chats': user?.chats,
        'newMessages': user?.newMessages,
        'birthDate': user?.birthDate,
        'goals': user?.goals,
        'isAdmin': user?.isAdmin,
        'receivedSecretVote': user?.receivedSecretVote,
        'wantsToTalk': user?.wantsToTalk,
        'discoveriesRemaning': user?.discoveriesRemaning,
        'typsenseId': user?.typsenseId,
        'randomInt': user?.randomInt,
        'isBanned': user?.isBanned,
        'banReason': user?.banReason,
        'banExpiration': user?.banExpiration,
        'seenWaveLikeNotification': user?.seenWaveLikeNotification,
        'seenVoteNotification': user?.seenVoteNotification,
        'verified': user?.verified,
        'seenTutorial': user?.seenTutorial,
        'castFirstVote': user?.castFirstVote,
        'newNotifications': user?.newNotifications,
        'blockedBy': user?.blockedBy,
        'blockedUsers': user?.blockedUsers,
        'blockedUserIds': user?.blockedUserIds,
        'createdAt': user?.createdAt,
        'isPup': user?.isPup,
      };

  static User fromDynamic(dynamic snap) {
    User user = User(
      id: snap['id'] ?? '',
      name: snap['name'] ?? '',
      age: yearsBetween(snap['birthDate'].toDate() ?? '', DateTime.now()),
      imageUrls: snap['imageUrls'] ?? [],
      interests: snap['interests'] ?? [],
      jobTitle: snap['jobTitle'] ?? '',
      bio: snap['bio'] ?? '',
      isStingray: snap['isStingray'] ?? false,
      email: snap['email'] ?? '',
      team: snap['team'] ?? null,
      instigations: snap['instigations'] ?? 0,
      votes: snap['votes'] ?? 0,
      votesUsable: snap['votesUsable'] ?? 0,
      isRude: snap['isRude'] ?? false,
      stingrays: snap['stingrays'] ?? [],
      finishedOnboarding: snap['finishedOnboarding'] ?? false,
      gender: snap['gender'] ?? '',
      chats: Chat.chatListFromMap(snap['chats']),
      newMessages: snap['newMessages'] ?? '',
      handle: snap['handle'] ?? '',
      goals: snap['goals'] ?? '',
      birthDate: snap['birthDate'].toDate() ?? '',
      isAdmin: snap['isAdmin'] ?? false,
      receivedSecretVote: snap['receivedSecretVote'] ?? false,
      wantsToTalk: snap['wantsToTalk'] ?? false,
      discoveriesRemaning: snap['discoveriesRemaning'] ?? 0,
      typsenseId: snap['typsenseId'] ?? '',
      randomInt: snap['randomInt'] ?? 0,
      isBanned: snap['isBanned'] ?? false,
      banReason: snap['banReason'] ?? '',
      banExpiration: snap['banExpiration'].toDate() ?? '',
      seenWaveLikeNotification: snap['seenWaveLikeNotification'] ?? false,
      seenVoteNotification: snap['seenVoteNotification'] ?? false,
      verified: snap['verified'] ?? false,
      seenTutorial: snap['seenTutorial'] ?? false,
      castFirstVote: snap['castFirstVote'] ?? false,
      newNotifications: snap['newNotifications'] ?? false,
      blockedBy: snap['blockedBy'] ?? [],
      blockedUsers: snap['blockedUsers'] ?? [],
      blockedUserIds: snap['blockedUserIds'] ?? [],
      createdAt: (snap['createdAt'] ??
              //timestamp of now
              Timestamp.fromDate(DateTime.now()))
          .toDate(),
      isPup: snap['isPup'] ?? false,
    );
    return user;
  }

  static User fromSnapshot(DocumentSnapshot snap) {
    Map<String, dynamic>? map = snap.data() as Map<String, dynamic>?;
    DateTime? banExpiration = map?['banExpiration']?.toDate();
    User user = User(
      id: map?['id'] ?? '',
      name: map?['name'] ?? '',
      age: yearsBetween(map?['birthDate'].toDate() ?? '', DateTime.now()),
      imageUrls: map?['imageUrls'] ?? [],
      interests: map?['interests'] ?? [],
      jobTitle: map?['jobTitle'] ?? '',
      bio: map?['bio'] ?? '',
      isStingray: map?['isStingray'] ?? false,
      email: map?['email'] ?? '',
      team: map?['team'] ?? null,
      instigations: map?['instigations'] ?? 0,
      votes: map?['votes'] ?? 0,
      votesUsable: map?['votesUsable'] ?? 0,
      isRude: map?['isRude'] ?? false,
      stingrays: map?['stingrays'] ?? [],
      finishedOnboarding: map?['finishedOnboarding'] ?? false,
      gender: map?['gender'] ?? '',
      chats: Chat.chatListFromMap(map?['chats']),
      newMessages: map?['newMessages'] ?? '',
      handle: map?['handle'] ?? '',
      goals: map?['goals'] ?? '',
      birthDate: map?['birthDate'].toDate() ?? '',
      isAdmin: map?['isAdmin'] ?? false,
      receivedSecretVote: map?['receivedSecretVote'] ?? false,
      wantsToTalk: map?['wantsToTalk'] ?? false,
      discoveriesRemaning: map?['discoveriesRemaning'] ?? 0,
      typsenseId: map?['typsenseId'] ?? '',
      randomInt: map?['randomInt'] ?? 0,
      isBanned: map?['isBanned'] ?? false,
      banReason: map?['banReason'] ?? '',
      banExpiration: banExpiration ?? DateTime.now(),
      seenWaveLikeNotification: map?['seenWaveLikeNotification'] ?? false,
      seenVoteNotification: map?['seenVoteNotification'] ?? false,
      verified: map?['verified'] ?? false,
      seenTutorial: map?['seenTutorial'] ?? false,
      castFirstVote: map?['castFirstVote'] ?? false,
      newNotifications: map?['newNotifications'] ?? false,
      blockedBy: map?['blockedBy'] ?? [],
      blockedUsers: map?['blockedUsers'] ?? [],
      blockedUserIds: map?['blockedUserIds'] ?? [],
      createdAt:
          (map?['createdAt'] ?? Timestamp.fromDate(DateTime.now())).toDate(),
      isPup: map?['isPup'] ?? false,
    );
    return user;
  }

  static List<User?> userListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map<User?>((doc) {
      Map map = doc.data() as Map;
      return User(
        id: doc['id'] ?? '',
        name: doc['name'] ?? '',
        age: yearsBetween(doc['birthDate'].toDate() ?? '', DateTime.now()),
        imageUrls: doc['imageUrls'] ?? [],
        interests: doc['interests'] ?? [],
        jobTitle: doc['jobTitle'] ?? '',
        bio: doc['bio'] ?? '',
        isStingray: doc['isStingray'] ?? false,
        email: doc['email'] ?? '',
        team: doc['team'] ?? null,
        instigations: doc['instigations'] ?? 0,
        votes: doc['votes'] ?? 0,
        votesUsable: doc['votesUsable'] ?? 0,
        isRude: doc['isRude'] ?? false,
        stingrays: doc['stingrays'] ?? [],
        finishedOnboarding: doc['finishedOnboarding'] ?? false,
        gender: doc['gender'] ?? '',
        handle: doc['handle'] ?? '',
        chats: Chat.chatListFromMap(doc['chats']),
        newMessages: doc['newMessages'],
        goals: doc['goals'] ?? '',
        birthDate: doc['birthDate'].toDate() ?? '',
        isAdmin: doc['isAdmin'] ?? false,
        receivedSecretVote: doc['receivedSecretVote'] ?? false,
        wantsToTalk: doc['wantsToTalk'] ?? false,
        discoveriesRemaning: doc['discoveriesRemaning'] ?? 0,
        typsenseId: doc['typsenseId'] ?? '',
        randomInt: doc['randomInt'] ?? 0,
        isBanned: doc['isBanned'] ?? false,
        banReason: doc['banReason'] ?? '',
        banExpiration: doc['banExpiration'].toDate() ?? '',
        seenWaveLikeNotification: doc['seenWaveLikeNotification'] ?? false,
        seenVoteNotification: doc['seenVoteNotification'] ?? false,
        verified: map['verified'] ?? false,
        seenTutorial: map['seenTutorial'] ?? false,
        castFirstVote: map['castFirstVote'] ?? false,
        newNotifications: map['newNotifications'] ?? false,
        blockedBy: map['blockedBy'] ?? [],
        blockedUsers: map['blockedUsers'] ?? [],
        blockedUserIds: map['blockedUserIds'] ?? [],
        createdAt: (map['createdAt'] ??
                //timestamp of now
                Timestamp.fromDate(DateTime.now()))
            .toDate(),
        isPup: map['isPup'] ?? false,
      );
    }).toList();
  }

  static User userFromTypsenseDoc(Map<dynamic, dynamic> e) {
    Map map = e['document'] as Map;
    return User(
      name: map['name'] as String? ?? '',
      id: map['id'] as String?,
      imageUrls: map['imageUrls'] as List<dynamic>? ?? [],
      handle: map['handle'] as String? ?? '',
      votes: map['votes'] as int? ?? 0,
      votesUsable: map['votesUsable'] as int? ?? 0,
      instigations: map['instigations'] as int? ?? 0,
      stingrays: map['stingrays'] as List<dynamic>? ?? [],
      isStingray: map['isStingray'] as bool? ?? false,
      isRude: map['isRude'] as bool? ?? false,
      isAdmin: map['isAdmin'] as bool? ?? false,
      finishedOnboarding: map['finishedOnboarding'] as bool? ?? false,
      wantsToTalk: map['wantsToTalk'] as bool? ?? false,
      receivedSecretVote: map['receivedSecretVote'] as bool? ?? false,
      interests: map['interests'] as List<dynamic>? ?? [],
      chats: [],
      newMessages: map['newMessages'] as bool? ?? false,
      birthDate: DateTime.fromMillisecondsSinceEpoch(map['birthDate'] * 1000),
      bio: map['bio'] as String? ?? '',
      age: yearsBetween(
          (DateTime.fromMillisecondsSinceEpoch(map['birthDate'] * 1000)),
          DateTime.now()),
      jobTitle: map['jobTitle'] as String,
      goals: map['goals'] as List<dynamic>,
      gender: map['gender'] as String,
      discoveriesRemaning: map['discoveriesRemaning'] as int,
      randomInt: map['randomInt'] as int,
      typsenseId: map['typsenseId'] as String,
      isBanned: (map['isBanned'] as bool?) ?? false,
      banReason: map['banReason'] as String? ?? '',
      banExpiration: DateTime.now(),
      seenVoteNotification: map['seenVoteNotification'] as bool? ?? false,
      seenWaveLikeNotification:
          map['seenWaveLikeNotification'] as bool? ?? false,
      verified: map['verified'] as bool? ?? false,
      seenTutorial: map['seenTutorial'] as bool? ?? false,
      castFirstVote: map['castFirstVote'] as bool? ?? false,
      newNotifications: map['newNotifications'] as bool? ?? false,
      blockedBy: map['blockedBy'] as List<dynamic>? ?? [],
      blockedUsers: map['blockedUsers'] as List<dynamic>? ?? [],
      blockedUserIds: map['blockedUserIds'] as List<dynamic>? ?? [],
      createdAt:
          DateTime.fromMillisecondsSinceEpoch((map['createdAt'] ?? 0) * 1000),
      isPup: map['isPup'] as bool? ?? false,
    );
  }

  //static method that takes a stingray and returns a user
  static User fromStingray(Stingray stingray) {
    return User(
      id: stingray.id,
      name: stingray.name,
      age: stingray.age,
      imageUrls: stingray.imageUrls,
      interests: stingray.interests,
      jobTitle: stingray.jobTitle,
      bio: stingray.bio,

      team: stingray.team,

      handle: stingray.handle,
      //fill in the data not in the stingray with empty values
      receivedSecretVote: false,
      isAdmin: false,
      isStingray: true,
      isRude: false,
      stingrays: [],
      birthDate: stingray.birthDate,
      chats: [],
      newMessages: false,
      finishedOnboarding: false,
      wantsToTalk: false,
      discoveriesRemaning: 0,
      typsenseId: stingray.id!,
      randomInt: 0,
      votes: 0,
      votesUsable: 0,
      instigations: 0,
      gender: stingray.gender,
      goals: [],
      isBanned: false,
      banReason: '',
      banExpiration: DateTime.now(),
      seenVoteNotification: false,
      seenWaveLikeNotification: false,
      verified: false,
      seenTutorial: false,
      castFirstVote: false,
      newNotifications: false,
      blockedBy: [],
      blockedUsers: [],
      blockedUserIds: [],
      createdAt: DateTime.now(),
      isPup: false,
    );
  }

  //copywith method that takes all the values of a user and returns a new user with the new values

  User? copyWith({
    String? id,
    String? name,
    int? age,
    List<dynamic>? imageUrls,
    List<dynamic>? interests,
    String? bio,
    String? jobTitle,
    String? gender,
    bool? isStingray,
    String? email,
    Team? team,
    int? votes,
    int? votesUsable,
    int? instigations,
    bool? isRude,
    List<dynamic>? stingrays,
    bool? finishedOnboarding,
    String? handle,
    List<Chat?>? chats,
    bool? newMessages,
    List<dynamic>? goals,
    DateTime? birthDate,
    bool? isAdmin,
    bool? receivedSecretVote,
    bool? wantsToTalk,
    int? discoveriesRemaning,
    String? typsenseId,
    int? randomInt,
    bool? isBanned,
    String? banReason,
    DateTime? banExpiration,
    bool? seenWaveLikeNotification,
    bool? seenVoteNotification,
    bool? verified,
    bool? seenTutorial,
    bool? castFirstVote,
    bool? newNotifications,
    List<dynamic>? blockedBy,
    List<dynamic>? blockedUsers,
    List<dynamic>? blockedUserIds,
    DateTime? createdAt,
    bool? isPup,
  }) {
    return User(
      id: id ?? this.id,
      name: name ?? this.name,
      age: age ?? this.age,
      imageUrls: imageUrls ?? this.imageUrls,
      interests: interests ?? this.interests,
      bio: bio ?? this.bio,
      typsenseId: typsenseId ?? this.typsenseId,
      finishedOnboarding: finishedOnboarding ?? this.finishedOnboarding,
      isAdmin: isAdmin ?? this.isAdmin,
      isStingray: isStingray ?? this.isStingray,
      isRude: isRude ?? this.isRude,
      stingrays: stingrays ?? this.stingrays,
      receivedSecretVote: receivedSecretVote ?? this.receivedSecretVote,
      wantsToTalk: wantsToTalk ?? this.wantsToTalk,
      discoveriesRemaning: discoveriesRemaning ?? this.discoveriesRemaning,
      birthDate: birthDate ?? this.birthDate,
      chats: chats ?? this.chats,
      newMessages: newMessages ?? this.newMessages,
      handle: handle ?? this.handle,
      votes: votes ?? this.votes,
      votesUsable: votesUsable ?? this.votesUsable,
      instigations: instigations ?? this.instigations,
      randomInt: randomInt ?? this.randomInt,
      goals: goals ?? this.goals,
      gender: gender ?? this.gender,
      jobTitle: jobTitle ?? this.jobTitle,
      team: team ?? this.team,
      email: email ?? this.email,
      isBanned: isBanned ?? this.isBanned,
      banReason: banReason ?? this.banReason,
      banExpiration: banExpiration ?? this.banExpiration,
      seenVoteNotification: seenVoteNotification ?? this.seenVoteNotification,
      seenWaveLikeNotification:
          seenWaveLikeNotification ?? this.seenWaveLikeNotification,
      verified: verified ?? this.verified,
      seenTutorial: seenTutorial ?? this.seenTutorial,
      castFirstVote: castFirstVote ?? this.castFirstVote,
      newNotifications: newNotifications ?? this.newNotifications,
      blockedBy: blockedBy ?? this.blockedBy,
      blockedUsers: blockedUsers ?? this.blockedUsers,
      blockedUserIds: blockedUserIds ?? this.blockedUserIds,
      createdAt: createdAt ?? this.createdAt,
      isPup: isPup ?? this.isPup,
    );
  }

  

}

Anyone know whats going on? and is there another way to import user_model.dart file?

Thanks!

CodePudding user response:

It is always better to use absolute path import as this keeps the folder directories consistent. To make your paths absolute you can change the import syntax of:

import '../models/user_model.dart';

To

import 'package:hero/models/user_model.dart';

It is always a good practice to provide file structure of the project for such questions because your parent folder may something else I have assumed it as hero

For more information about this topic go through this thread which explains this absolute vs relative imports.

  • Related